CtrlK
BlogDocsLog inGet started
Tessl Logo

ai-agents-development

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.

SKILL.md
Quality
Evals
Security

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 on that failure, so you get no partial state — but you do waste the round trip.

Naming and Description Constraints

Both artifacts share the CLI's standard validators at create time. These bite constantly:

ConstraintRule
Name length5–100 characters at create — kb, agent, and bot all fail
Name charactersAlphanumeric plus space and ' [ ] ( ) . _ - — must start with alphanumeric
Description length3–500 characters when present (optional, but -d "x" fails)
Description charactersAlphanumeric, whitespace, and : ' [ ] ( ) , . / _ -
UniquenessAgent 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.

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.

# 1. Knowledge base FIRST. --files is REQUIRED with --no-prompt.
#    Accepts local paths and HTTP(S) URLs (downloaded at create time).
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
#    --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:

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. The manifest is saved before the directory is removed, so a failed removal reports an orphaned directory by path rather than losing the manifest edit.

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.

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.

Input and output formats

FlagAllowed valuesDefaultPaired requirement
--input-formattext, jsontextjson requires --input-schema, and the file must be named input_schema.json
--output-formattext, json, json_with_schema, markdown, htmltextjson_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:

agent "my_agent" input_schema is required when input_format is json

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. CLIs newer than 2.1.1 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.

Manifest Structure

Everything lands under one top-level ai: key, which is omitted entirely when empty:

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
            - collections.triage_notes.CreateObject
            - api_integrations.VirusTotal.Get_a_file_report
          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

On disk:

agents/Detection_Triage_Agent/system_prompt.txt
knowledge-bases/Threat_Intel_Docs/runbook.md
knowledge-bases/Threat_Intel_Docs/iocs.csv

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.

  • 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.
  • tools — a flat list of dotted 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.

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:

FlagManifest keyEffect when true
--expose-charlotte-chatcharlotte_chatAgent is reachable from Charlotte chat
--expose-agent-as-toolagent_as_toolAgent can be invoked as a tool by other agents
--expose-workflow-system-actionworkflows.system_actionAgent 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).

  • --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
  • 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 a dotted string. 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.

TargetFormatExample
App collectioncollections.<collection_name>.<Operation>collections.triage_notes.CreateObject
Agent runtime collectioncollections.generic.<Operation>collections.generic.ListObjects
API integrationapi_integrations.<name>.<agent_tools.name>api_integrations.VirusTotal.Get_a_file_report

Valid collection operations — exact casing required:

CreateObject, GetObject, DeleteObject, ListObjects, SearchObjects

collections.generic.* refers to 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.

For API integrations the final segment is the operation's name from the OpenAPI spec's x-cs-operation-config.agent_tools.name, not the raw path.

Exposing the target artifact

# 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

That writes agent_tools_integration: {exposed: true} onto the collection. See collections-development for schema design.

API integrations opt in per operation inside the OpenAPI spec, alongside the workflow config:

"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
  }
}

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.

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.

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

SymptomCauseFix
must be at least 5 characters longName under 5 chars at createLengthen the name; kb and agent are both too short
invalid value for --descriptionDescription under 3 charsWrite a real description or omit -d
references knowledge base "X" which is not definedAgent created before its KBCreate the KB first, then re-run the agent command
flag --files is required when --no-prompt flag is usedKB create without --filesKBs must ship at least one file
input_schema is required when input_format is jsonFormat/schema mismatchPass the paired --input-schema
--input-schema is required when --expose-agent-as-tool is setAgent exposed as a tool with no declared signatureAdd --input-schema, or drop the exposure flag
input_schema is required when exposure.agent_as_tool is trueHand-added agent_as_tool to an agent with no input schemaAdd input_schema to that agent, or set the flag back to false
flag --name is required when --no-prompt flag is useddelete without --namePass the artifact name as it appears in manifest.yml
still referenced by agent(s): YDeleting a KB an agent still listsDelete the agent first, or remove the KB from its knowledge_bases
file <name> already existsRe-running KB create over existing filesDelete the file or the KB directory first
System prompt is a file path stringTypo'd --system-prompt path fell back to inline textRead back agents/<path>/system_prompt.txt
KB file missing after deploy.svg files are always ignored by the packagerConvert to PNG, or reference it another way
must be a filename only, not a pathSubdirectory in a KB files entryFlatten — KB directories cannot nest
Agent cannot call an exposed collectionExposed but not listed in toolsBoth sides are required
output_schema must be "output_schema.json" (or input_schema ...) on any command, or output schema is required when using JSON format at deploySchema file not named output_schema.json (input_schema.json), or an inline schemaPut 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
model <id> does not support structured output at deployjson_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 > AgentWorksagents delete + redeploy left the old platform-side agent unpublishedDelete 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 agentPick 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_limitValue below the undocumented floorPass 100 or more

Reading Guide

TaskReference
KB file sourcing, encryption, deploy packaging limitsreferences/knowledge-bases.md
Full field-by-field schema, every validation error stringreferences/manifest-schema.md
Product docs: Falcon Foundry AI capabilities overviewAI Capabilities
Product docs: agents via the CLIAI agents (Foundry CLI)
Product docs: knowledge bases via the CLIKnowledge bases (Foundry CLI)

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
Repository
CrowdStrike/foundry-skills
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.