v1.6.0 to v1.6.0

42 added, 132 removed. Audit A to A.

---
name: ai-agents-development
description: Build AI agents and knowledge bases for Falcon Foundry apps. TRIGGER when user asks to "create an AI agent", "add a Foundry agent", "build a knowledge base", "give my agent documents", "expose a collection as an agent tool", "expose an API operation to an agent", "put my agent in Charlotte", "expose an agent as a tool for other agents", "delete an agent or knowledge base", runs `foundry agents create`, `foundry agents delete`, `foundry knowledge-bases create`, or `foundry knowledge-bases delete`, or needs help with the `ai.agents` / `ai.knowledge_bases` manifest blocks, agent system prompts, agent input/output formats, agent exposure, or agent tool references. DO NOT TRIGGER for Fusion SOAR workflow YAML — use workflows-development. DO NOT TRIGGER for serverless function handlers — use functions-development. DO NOT TRIGGER for designing a collection schema itself — use collections-development, then return here to wire the collection up as an agent tool.
version: 1.6.0
updated: 2026-10-01
tags: [foundry, ai, agents, knowledge-bases, charlotte, agent-tools]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
metadata:
category: ai
---
# Foundry AI Agents and Knowledge Bases
> Create knowledge bases before the agents that reference them, and scaffold both with the CLI.
> **Part of a suite.** If `development-workflow` has not already run, and this is a new app or its first capability, load the `development-workflow` skill first — it owns the CLI prerequisite check, scaffolding order, and manifest coordination.
An **AI agent** is a Foundry artifact that pairs a system prompt with a model, a set of tools, and optional knowledge bases. A **knowledge base** is a named bundle of files the agent can draw on. Both live under a single `ai:` block in `manifest.yml`.
Agents are the only consumer of knowledge bases. A knowledge base on its own does nothing; a collection or API integration becomes agent-usable only when it is exposed as a tool and named in the agent's `tools` list.
## Build Order Is Mandatory
```
1. Collections / API integrations (if the agent needs them as tools)
2. Knowledge bases → foundry knowledge-bases create
3. Agents → foundry agents create (exposure via --expose-* flags)
4. Hand-edit ai.agents[].model / .tools (no CLI flags exist for these two)
```
**Create knowledge bases first.** `foundry agents create --knowledge-bases X` validates that `X` is already in the manifest and fails the whole command otherwise:
```
agent "my_agent" references knowledge base "X" which is not defined in the manifest
```
The agent directory is rolled back, so nothing is left half-created.
## Naming and Description Constraints
- Both artifacts share the CLI's standard validators at create time. These bite constantly:
-
- | Constraint | Rule |
- |-----------|------|
- | Name length | **5–100 characters** at create — `kb`, `agent`, and `bot` all fail |
- | Name characters | Alphanumeric plus space and `' [ ] ( ) . _ -` — must start with alphanumeric |
- | Description length | 3–500 characters when present (optional, but `-d "x"` fails) |
- | Description characters | Alphanumeric, whitespace, and `: ' [ ] ( ) , . / _ -` |
- | Uniqueness | Agent names unique among agents; KB names unique among KBs |
-
- Knowledge bases are the one asymmetry: the create command enforces the 5-character floor, but the *manifest* validator only requires 1 character and no longer checks the description at all. So `--name "kb"` is rejected by `knowledge-bases create`, but a manifest that already carries a short KB name passes `foundry apps validate`.
-
- The on-disk directory is a sanitized form of the name: every character outside `[a-zA-Z0-9-_]` becomes `_`. `--name "Threat Intel Docs"` yields `knowledge-bases/Threat_Intel_Docs/` and records `path: Threat_Intel_Docs`. The manifest resolves files against `path`, never against `name`.
+ Both artifacts share the CLI's create-time validators, which bite constantly: **names are 5–100 chars** (must start alphanumeric; `kb`, `agent`, `bot` all fail), **descriptions 3–500 chars** when present (`-d "x"` fails), agent names unique among agents and KB names among KBs. KBs are the one asymmetry — `knowledge-bases create` enforces the 5-char floor, but the *manifest* validator accepts a KB name as short as 1 character (and no longer checks the description), so a short name already in the manifest passes `apps validate`. The on-disk directory is a sanitized form of the name (every char outside `[a-zA-Z0-9-_]` → `_`): `--name "Threat Intel Docs"` yields `knowledge-bases/Threat_Intel_Docs/` and records `path: Threat_Intel_Docs`; the manifest resolves files against `path`, never `name`. Full regex/length table: [references/manifest-schema.md](references/manifest-schema.md#shared-validators).
## CLI Scaffolding
Both artifacts support `create` and `delete`. There is no `list` or `edit` — to rename or reconfigure an existing agent beyond the hand-editable fields, delete it and create it again.
```bash
- # 1. Knowledge base FIRST. --files is REQUIRED with --no-prompt.
- # Accepts local paths and HTTP(S) URLs (downloaded at create time).
+ # 1. Knowledge base FIRST (--files REQUIRED with --no-prompt; accepts local paths and HTTP(S) URLs).
foundry knowledge-bases create \
--name "Threat Intel Docs" \
--description "Runbooks and IOC references" \
--files ./runbook.md,./iocs.csv \
--no-prompt
- # 2. Agent SECOND, referencing the KB by NAME (not id, not path).
- # Plain json needs no schema. For enforced structure use json_with_schema with
+ # 2. Agent SECOND, referencing the KB by NAME. Plain json needs no schema; json_with_schema needs
# --output-schema pointing at a file named output_schema.json (see below).
foundry agents create \
--name "Detection Triage Agent" \
--description "Triages detections against the runbooks" \
--system-prompt ./prompts/triage.md \
--knowledge-bases "Threat Intel Docs" \
--output-format json \
--expose-charlotte-chat \
--no-prompt
```
`foundry kb create` is a working alias for `knowledge-bases create`.
### Deleting agents and knowledge bases
- `delete` removes the manifest entry **and** the artifact's directory. It takes `--name` plus the usual `--no-prompt`, exactly like every other Foundry command:
+ `delete` removes the manifest entry **and** the artifact's directory. It takes `--name` (matching `manifest.yml`) plus `--no-prompt` (required — an unknown name then fails fast instead of opening a picker):
```bash
foundry agents delete --name "Detection Triage Agent" --no-prompt
foundry knowledge-bases delete --name "Threat Intel Docs" --no-prompt
```
- `--name` must match the name in `manifest.yml`; with `--no-prompt` it is required (`flag --name is required when --no-prompt flag is used`) and an unknown name fails fast rather than opening a picker.
-
- A knowledge base still referenced by an agent cannot be deleted:
-
- ```
- cannot delete knowledge base "Threat Intel Docs": still referenced by agent(s): Detection Triage Agent
- ```
-
- Delete the agent first, or remove the KB from its `knowledge_bases` list. Deleting the last artifact leaves the empty `agents/` and `knowledge-bases/` parent directories behind; that is harmless.
-
- `delete` is local-only. The next deploy leaves the previously deployed agent in Charlotte AI > AgentWorks as an unpublished orphan, so recreating one under the same name shows two entries. Remove the orphan by hand in the console, and match agents at runtime by the IDs in `manifest.yml`, not by name. `foundry apps delete` does remove the platform-side agents.
+ A KB still referenced by an agent cannot be deleted (`cannot delete knowledge base "X": still referenced by agent(s): …`) — delete the agent first, or remove the KB from its `knowledge_bases` list. Deleting the last artifact leaves the empty parent dirs behind (harmless). `delete` is local-only: the next deploy leaves the previously deployed agent in Charlotte AI > AgentWorks as an unpublished orphan (recreating under the same name shows two entries), so remove the orphan by hand and match agents at runtime by the IDs in `manifest.yml`, not by name. `foundry apps delete` does remove the platform-side agents.
### The `--system-prompt` value is a path *or* literal text
- The CLI tries to read the value as a file path or URL first, and silently falls back to treating it as inline prompt text when that fails. Either way the content is written to `agents/<path>/system_prompt.txt`, always under that exact filename.
-
- Consequence: a typo'd path becomes your system prompt. `--system-prompt ./prmopts/triage.md` produces an agent whose entire instruction set is the string `./prmopts/triage.md`, with no error. **Always read back `agents/<path>/system_prompt.txt` after creating an agent.** Omitting the flag entirely yields a generic default prompt.
+ The CLI reads the value as a file path/URL first and silently falls back to treating it as inline prompt text when that fails — always writing to `agents/<path>/system_prompt.txt`. So a typo'd path (`./prmopts/triage.md`) becomes your entire system prompt with no error. **Always read back `agents/<path>/system_prompt.txt` after creating an agent.** Omitting the flag yields a generic default prompt.
### Input and output formats
| Flag | Allowed values | Default | Paired requirement |
|------|---------------|---------|--------------------|
| `--input-format` | `text`, `json` | `text` | `json` requires `--input-schema`, and the file **must be named `input_schema.json`** |
| `--output-format` | `text`, `json`, `json_with_schema`, `markdown`, `html` | `text` | `json_with_schema` requires `--output-schema`, and the file **must be named `output_schema.json`** (see below) |
- Note the asymmetry: `output_format: json` needs **no** schema, only `json_with_schema` does. Omitting the paired schema is caught late, when the manifest is saved:
+ Note the asymmetry: `output_format: json` needs **no** schema; only `json_with_schema` does. Omitting the paired schema is caught late at manifest save (`agent "my_agent" input_schema is required when input_format is json`).
- ```
- agent "my_agent" input_schema is required when input_format is json
- ```
+ > **The schema file name is fixed** — it must be `input_schema.json` / `output_schema.json` in the agent directory (a manifest key naming any other file breaks every CLI command in the app; CLI 2.1.2+ renames the file you pass to `--input-schema`/`--output-schema`), and the bound schema is re-validated against the agent's model at deploy (unsupported keywords like `minimum`/`maximum` surface only in App manager "Show errors"). Full error strings + allowed keywords: [references/manifest-schema.md](references/manifest-schema.md#schema-file-names-are-fixed).
- > **The schema file name is fixed.** The Foundry API reads only `input_schema.json` and `output_schema.json` from the agent directory, ignoring any other filename or an inline schema. Give the local file passed to `--output-schema` (`--input-schema`) that name first, downloading a URL source if needed. CLI 2.1.2 and later write the schema under that name whatever you pass, and reject any other value on every manifest load, so a wrong name breaks every command in the app:
- >
- > ```
- > agent "my_agent" output_schema must be "output_schema.json": rename agents/my_agent/verdict.json to output_schema.json and set output_schema: output_schema.json in manifest.yml
- > ```
- >
- > CLI 2.1.1 and earlier keep the source name, pass `apps validate`, and fail deploy with `output schema is required when using JSON format` (verified 2026-09-22). Either way, put the schema at `agents/<path>/output_schema.json` (`input_schema.json`) and set the matching key to that name.
- >
- > Once bound, the schema is validated against the agent's model at deploy, and that failure is only visible in App manager > app > deployment > "Show errors": for example `output schema at root.properties.score uses unsupported schema keyword maximum, minimum` for Claude on Bedrock. Stick to `type`, `properties`, `required`, `enum`, `description`, and `additionalProperties: false`; put ranges in `description`. OpenAI models also need `additionalProperties: false` on every object and every property in `required`.
+ ### Keeping a large-JSON agent from bailing to prose or timing out
+ An agent asked for a big structured object fails two ways: it emits a prose preamble before the JSON (breaking downstream `JSON.parse`), or it runs long enough that the action times out (observed at about 10 minutes). The driver is almost always **output + reasoning volume, not input size** — a large prompt with a small, capped output is fine; a modest prompt asking for an unbounded list is not. Fixes, in order:
+
+ 1. Impose a hard **output contract** in the system prompt: top-N caps on every array, terse field values, and an explicit "emit only the JSON object — no preamble or explanation before or after it."
+ 2. Lower reasoning volume. A manifest agent has no reasoning setting (see below), so for it rely on 1 and 3. For an agent built in AgentWorks, open its **Agent configuration** page, open the menu, select **Model settings**, and set **Reasoning Effort** lower; a high **Maximum Length** can also cause timeouts.
+ 3. **Split the agent** (per-domain shards + a deterministic merge function) only if a capped single-shot still overflows; a split adds workflow nodes and cost, so exhaust 1–2 first.
+ 4. As a last resort, add a **client-side JSON salvage** in the renderer (drop anything before the first `{` / after the last `}`, then parse) so a stray preamble degrades gracefully instead of blanking the view.
+
`output_format: json` drops replies that aren't valid JSON, and agents the app creates are app-owned: see [manifest-schema](references/manifest-schema.md#output-format-json-and-long-replies).
## Manifest Structure
- Everything lands under one top-level `ai:` key, which is omitted entirely when empty:
+ Both artifact lists live under one top-level `ai:` key (omitted when empty) — never a top-level `agents:` key. This is a shape sketch, not YAML to copy; the CLI writes the entries:
```yaml
ai:
- agents:
- - id: cfa84addde80471fb2ffcb67460ca688 # CLI-generated, 32 hex chars
- name: Detection Triage Agent
- description: Triages detections against the runbooks
- path: Detection_Triage_Agent # sanitized name
- model: "" # empty unless the user named one
- tools: # hand-edited, see below
- - action:collections.triage_notes.CreateObject
- system_prompt: system_prompt.txt
- input_format: text
- output_format: json # json_with_schema adds output_schema: output_schema.json
- knowledge_bases:
- - Threat Intel Docs # by NAME
- exposure: # omitted entirely when nothing is exposed
- workflows:
- system_action: false
- charlotte_chat: true
- agent_as_tool: false
- knowledge_bases:
- - id: 328ff55985c24616ad895336b855c90d
- name: Threat Intel Docs
- description: Runbooks and IOC references
- encrypt: false
- path: Threat_Intel_Docs
- files: # bare filenames only
- - runbook.md
- - iocs.csv
+ agents: # ai.agents[]: id, name, description, path, model, tools,
+ - id: … # system_prompt, input/output_format, knowledge_bases (by NAME), exposure
+ knowledge_bases: # ai.knowledge_bases[]: id, name, description, encrypt, path, bare-filename files
+ - id: …
```
- On disk:
-
- ```
- agents/Detection_Triage_Agent/system_prompt.txt
- knowledge-bases/Threat_Intel_Docs/runbook.md
- knowledge-bases/Threat_Intel_Docs/iocs.csv
- ```
+ System prompts live at `agents/<path>/system_prompt.txt`; KB files at `knowledge-bases/<path>/<file>`. Full annotated YAML + on-disk layout: [references/manifest-schema.md](references/manifest-schema.md#full-worked-example).
## Two Fields the CLI Cannot Set
`model` and `tools` have **no CLI flags**. `foundry agents create` always writes `model: ""` and omits `tools`. Configuring them means editing `manifest.yml` directly.
- > **This is a narrow, explicit exception to the plugin-wide rule against editing `manifest.yml`**, which protects the CLI-owned `id`, `path`, `entrypoint`, and scopes. These two fields have no CLI path at all. Edit **only** these keys under `ai.agents[]` (plus a schema key that names the wrong file; see above); leave `id`, `path`, `system_prompt`, and every other artifact's entries alone.
+ > **This is a narrow, explicit exception to the plugin-wide rule against editing `manifest.yml`** (which protects the CLI-owned `id`, `path`, `entrypoint`, scopes). Edit **only** `model`/`tools` under `ai.agents[]` (plus a schema key naming the wrong file); leave everything else alone.
- - **`model`** — **never invent a model ID.** There is no client-side list of valid IDs, so anything you make up produces a manifest that validates locally and fails server-side at deploy. Three cases:
- - **Nothing supplied** — leave `""`. The platform default applies.
- - **User named a specific model** — write exactly what they gave you, and tell them it is only checked server-side at deploy. Honoring their choice is correct even if it later fails; guessing a "close enough" ID on their behalf is not.
- - **A value is already there** — leave it alone. Do not blank it out or substitute your own.
+ - **`model`** — **never invent a model ID** (there's no client-side list, so a made-up ID validates locally and fails server-side at deploy). Nothing supplied → leave `""` (platform default). User named one → write it verbatim and note it's only checked at deploy; don't guess a "close enough" ID. Already set → leave it.
- **`tools`** — a list of `<type>:<reference>` strings, not validated client-side. See below.
- **No other tuning knobs exist.** Agents have no temperature or token settings, and knowledge bases have no chunk size, embedding, similarity, or `top_k`; indexing is server-side. Never add such keys to the manifest. Tell the user those settings aren't available.
+ **No other tuning knobs exist in `manifest.yml`.** Manifest agents have no temperature, maximum length, or reasoning settings (agents built in AgentWorks set those under **Model settings**), and knowledge bases have no chunk size, embedding, similarity, or `top_k`; indexing is server-side. Never add such keys to the manifest. Tell the user those settings aren't available.
## Agent Exposure
`exposure` controls where the agent can be reached from. Unlike `model` and `tools`, it **does** have CLI flags, so prefer setting it at create time:
| Flag | Manifest key | Effect when `true` |
|------|--------------|--------------------|
| `--expose-charlotte-chat` | `charlotte_chat` | Agent is reachable from Charlotte chat |
| `--expose-agent-as-tool` | `agent_as_tool` | Agent can be invoked as a tool by other agents |
| `--expose-workflow-system-action` | `workflows.system_action` | Agent is published as an app-scoped Fusion action |
Three behaviors worth knowing:
- - **No flag means unreachable, even by your own app.** With no `--expose-*` flag the `exposure` block is omitted (same as all three `false`), and no workflow can call the agent. For an agent used only by this app's automations, pass `--expose-workflow-system-action` alone; it stays out of Charlotte chat. Call it from the app's workflows as `ai_agents.<agent name>`, never a generic LLM action with the prompt copied inline ([workflow-invocation](references/workflow-invocation.md)).
- - **`--expose-agent-as-tool` requires `--input-schema`.** A calling agent needs a declared signature to invoke this one. The check runs before any files are written:
-
- ```
- --input-schema is required when --expose-agent-as-tool is set
- ```
-
- The same rule is enforced on the manifest, so hand-adding `agent_as_tool: true` to an agent with no `input_schema` breaks every subsequent CLI command in that app:
-
- ```
- agent "X" input_schema is required when exposure.agent_as_tool is true
- ```
-
+ - **No flag means unreachable, even by your own app.** With no `--expose-*` flag the `exposure` block is omitted entirely when nothing is exposed (the same as all three `false`) — an absent block is correct, not a missing default to "repair" — and no workflow can call the agent. For an agent used only by this app's automations, pass `--expose-workflow-system-action` alone; it stays out of Charlotte chat. Call it from the app's workflows as `ai_agents.<agent name>`, never a generic LLM action with the prompt copied inline ([workflow-invocation](references/workflow-invocation.md)).
+ - **`ai_agents.<name>` binds only to an agent in this app's `ai.agents` block.** The alias resolves against that agent's manifest `name`, nothing else. An agent already in the CID but not in this app's manifest (one built in Charlotte AI > AgentWorks, say) has no manifest entry, so `ai_agents.<its name>` resolves to nothing. A workflow can reach such an agent only by its resolved `<uuid>_<cid>` action ID, which differs in every CID, so the workflow won't port. To make it portable, recreate the agent as a manifest agent: that's a new, app-owned copy, not a link to the AgentWorks one.
+ - **An AgentWorks agent must be published before a workflow that references it deploys.** Only an agent's published version is exposed to Falcon Fusion SOAR workflows. Deploy a workflow that references an unpublished agent's `<uuid>_<cid>` and Falcon Fusion SOAR rejects it with `(2015) action <uuid>_<cid> does not exist`. Publish the agent in AgentWorks, then deploy.
+ - **`--expose-agent-as-tool` requires `--input-schema`.** A calling agent needs a declared signature; the check runs before any files are written (`--input-schema is required when --expose-agent-as-tool is set`), and the same rule is enforced on the manifest, so hand-adding `agent_as_tool: true` without an `input_schema` breaks every subsequent CLI command in the app.
- **Nothing else here is validated client-side.** A misspelled key under `exposure` surfaces only at deploy.
Adding or removing exposure after create means editing `manifest.yml` (or deleting and re-creating the agent) — there is no `agents edit`.
## Agent Tool References
Each `tools` entry is `<type>:<reference>`. The artifact must be exposed on its own side *and* named here — one without the other produces an agent that silently cannot call it, with no error at validate or deploy.
| Target | Entry |
|--------|-------|
| App collection | `action:collections.<collection_name>.<Operation>` |
| Agent runtime collection | `action:mcp/gce/collections:collections:generic:<Operation>` |
| API integration | `action:mcp/gce/integration:<integration id>~<hash>` (its platform tool ID) |
- Any other form fails the whole deploy, usually with a bare `500`. An API-integration tool ID exists only after the integration deploys, so deploy without that entry, look the ID up, then add it. See [manifest-schema](references/manifest-schema.md#tool-reference-format).
-
- Valid collection operations — exact casing required:
-
- `CreateObject`, `GetObject`, `DeleteObject`, `ListObjects`, `SearchObjects`
-
- The generic collection is a scratch collection the platform creates for the agent at runtime. Use it for agent working memory; use a named app collection when the data must outlive the agent or be readable by other capabilities.
-
- ### Exposing the target artifact
+ Any other form fails the whole deploy, usually with a bare `500`. A concrete `tools` entry (note the required `action:` prefix) looks like:
- ```bash
- # Collections: one flag at create time
- foundry collections create --name "triage_notes" --schema /tmp/schema.json \
- --description "Agent triage notes" --agent-tools-expose --no-prompt
+ ```yaml
+ tools:
+ - action:collections.triage_notes.CreateObject
```
- That writes `agent_tools_integration: {exposed: true}` onto the collection. See `collections-development` for schema design.
+ An API-integration tool ID exists only after the integration deploys, so deploy without that entry, look the ID up, then add it. See [manifest-schema](references/manifest-schema.md#tool-reference-format).
- API integrations opt in per operation inside the OpenAPI spec, alongside the workflow config:
+ Valid collection operations — exact casing required:
- ```json
- "x-cs-operation-config": {
- "agent_tools": {
- "name": "Get_a_file_report",
- "description": "get a file report",
- "expose_to_agent": true
- },
- "workflow": {
- "name": "Get a file report",
- "description": "Get a file report",
- "system": false
- }
- }
- ```
+ `CreateObject`, `GetObject`, `DeleteObject`, `ListObjects`, `SearchObjects`
- `agent_tools` and `workflow` are independent — an operation can be exposed to agents, to workflows, to both, or to neither. See `api-integrations` for spec adaptation.
+ The generic collection is a scratch collection the platform creates for the agent at runtime. Use it for agent working memory; use a named app collection when the data must outlive the agent or be readable by other capabilities.
- No other artifact type supports agent-tool exposure. Functions, workflows, and RTR scripts have no equivalent flag; to let an agent reach a function, expose the function to workflows and have the agent trigger the workflow.
+ Exposing the target artifact on its own side — the collection `--agent-tools-expose` flag and the API-integration `x-cs-operation-config.agent_tools` block — is covered in [references/manifest-schema.md](references/manifest-schema.md#exposing-an-artifact-as-an-agent-tool) (and owned by `collections-development` / `api-integrations`). No other artifact type supports agent-tool exposure; to reach a function, expose it to workflows and have the agent trigger the workflow.
## Invoking an Agent from Code
Charlotte chat and the app's own workflows (`ai_agents.<agent name>`) invoke an agent for you. Calling the agent definition API yourself (from a function or the UI) has one thing the API reference does not spell out:
- **`credit_cents_limit` has an undocumented floor of `100`.** Lower values are rejected with a `400`, so budget in whole credits.
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| `must be at least 5 characters long` | Name under 5 chars at create | Lengthen the name; `kb` and `agent` are both too short |
| `invalid value for --description` | Description under 3 chars | Write a real description or omit `-d` |
| `references knowledge base "X" which is not defined` | Agent created before its KB | Create the KB first, then re-run the agent command |
| `flag --files is required when --no-prompt flag is used` | KB create without `--files` | KBs must ship at least one file |
| `input_schema is required when input_format is json` | Format/schema mismatch | Pass the paired `--input-schema` |
| `--input-schema is required when --expose-agent-as-tool is set` | Agent exposed as a tool with no declared signature | Add `--input-schema`, or drop the exposure flag |
| `input_schema is required when exposure.agent_as_tool is true` | Hand-added `agent_as_tool` to an agent with no input schema | Add `input_schema` to that agent, or set the flag back to `false` |
| `flag --name is required when --no-prompt flag is used` | `delete` without `--name` | Pass the artifact name as it appears in `manifest.yml` |
| `still referenced by agent(s): Y` | Deleting a KB an agent still lists | Delete the agent first, or remove the KB from its `knowledge_bases` |
| `file <name> already exists` | Re-running KB create over existing files | Delete the file or the KB directory first. As a deploy `409`: see [knowledge-bases](references/knowledge-bases.md) |
| System prompt is a file path string | Typo'd `--system-prompt` path fell back to inline text | Read back `agents/<path>/system_prompt.txt` |
| KB file missing after deploy | `.svg` files are always ignored by the packager | Convert to PNG, or reference it another way |
| `must be a filename only, not a path` | Subdirectory in a KB `files` entry | Flatten — KB directories cannot nest |
| Agent cannot call an exposed collection | Exposed but not listed in `tools` | Both sides are required |
| Bare `500` from deploy, agent has `tools` | An entry isn't in a form from Agent Tool References | Fix the entry |
- | `output_schema must be "output_schema.json"` (or `input_schema ...`) on any command, or `output schema is required when using JSON format` at deploy | Schema file not named `output_schema.json` (`input_schema.json`), or an inline schema | Put the schema at `agents/<path>/output_schema.json` (`input_schema.json`) and set the manifest key to that name |
- | Deploy `Failed` with `output schema at root.properties.X uses unsupported schema keyword ...` in App manager "Show errors" | Schema keyword the agent's model provider rejects (`minimum`/`maximum` for Claude on Bedrock) | Drop the keyword and state the constraint in `description`; for OpenAI models also set `additionalProperties: false` on every object and list every property in `required` |
+ | `output_schema must be "output_schema.json"` (or `input_schema …`), or `output schema is required when using JSON format` at deploy | Schema file misnamed, or an inline schema | Name it `output_schema.json` / `input_schema.json` under `agents/<path>/`; see [manifest-schema](references/manifest-schema.md#schema-file-names-are-fixed) |
+ | Deploy `Failed` with `output schema … uses unsupported schema keyword …` in App manager "Show errors" | Keyword the agent's model provider rejects (`minimum`/`maximum` on Claude/Bedrock) | Drop it, state the constraint in `description`; see [manifest-schema](references/manifest-schema.md#schema-file-names-are-fixed) |
| `model <id> does not support structured output` at deploy | `json_with_schema` on a model without it (Bedrock Claude and Nemotron, as of 2026-09) | Use `output_format: json` for that agent, or a model that supports it (`openai.gpt-5.5` does) |
| Two agents with the same name in Charlotte AI > AgentWorks | `agents delete` + redeploy left the old platform-side agent unpublished | Delete the orphan in the console; match agents by the IDs in `manifest.yml`, not by name |
| Deploy fails with `model <id> is not available`, and still fails after setting `model: ""` | Model IDs are CID-specific, and a failed deploy leaves the pinned model on the platform-side agent | Pick an ID from `/agentic-studio/queries/models/v1` in that CID, or remove the agent and create it again |
| `400` when invoking an agent with `credit_cents_limit` | Value below the undocumented floor | Pass `100` or more |
+ | Deploy fails with Falcon Fusion SOAR `(2015) action <uuid>_<cid> does not exist` | Workflow references an AgentWorks agent that isn't published yet | Publish the agent in Charlotte AI > AgentWorks first, then deploy the referencing workflow. For the other cause of 2015, see [workflow-invocation.md](references/workflow-invocation.md) |
+ | Agent's JSON won't `JSON.parse`, or the action times out (observed at about 10 minutes) | Prose preamble before the JSON, or output/reasoning volume too high (not input size) | Output contract (top-N caps, terse fields, "no preamble"); for an AgentWorks agent, lower **Reasoning Effort** in **Model settings**; split only if still overflowing; client-side JSON salvage as fallback |
## Reading Guide
| Task | Reference |
|------|-----------|
| KB sourcing, encryption, packaging, changes after deploy | [references/knowledge-bases.md](references/knowledge-bases.md) |
| Full field-by-field schema, every validation error string | [references/manifest-schema.md](references/manifest-schema.md) |
| Product docs: Falcon Foundry AI capabilities overview | [AI Capabilities](https://docs.crowdstrike.com/access?ft:originId=ce325bab) |
| Product docs: agents via the CLI | [AI agents (Foundry CLI)](https://docs.crowdstrike.com/access?ft:originId=d82146c3) |
| Product docs: knowledge bases via the CLI | [Knowledge bases (Foundry CLI)](https://docs.crowdstrike.com/access?ft:originId=l69669e4) |
## Related Skills
- `collections-development` — schema design for collections used as agent tools
- `api-integrations` — OpenAPI spec work, including `x-cs-operation-config`
- `workflows-development` — Fusion workflows that call the agent as `ai_agents.<agent name>`
- `security-patterns` — prompt-injection surface review before exposing an agent to Charlotte
- `debugging-workflows` — deploy and validation failures