Skip to content

Agent specification reference

An agent is fully described by a JSON configuration document stored in the registry. This page is the authoritative reference for that format.

{
"assistant_id": "support-bot",
"nickname": "Support Bot",
"description": "Answers product support questions",
"response": {
"provider_id": "alquimia",
"profile": {
"system_prompt": "You are a helpful support assistant. Answer concisely.",
"evaluation_strategy": { "evaluation_strategy_id": "one-shoot" },
"persistence_strategy": "INCREMENTAL"
},
"config": {
"provider_id": "openai",
"params": {
"model": "gpt-4o-mini",
"api_key": { "$secretRef": "RESPONSE_PROVIDER_API_KEY" }
}
}
}
}
FieldTypeRequiredDescription
assistant_idstringYesUnique agent identifier within the agentspace
nicknamestringNoHuman-readable name (max 64 characters)
descriptionstringNoDescription shown in discovery and A2A tool lists (max 3000 characters)
tagsstring[]NoLabels for registry queries
channelsChannel[]NoInbound/outbound channel configurations
shieldsobjectNoPre-inference classifiers keyed by shield name
empathyEmpathyEngineNoConditional profile overrides based on shield output
role"reader" | "editor" | "operator"NoZero Trust capability tier ceiling
responseResponseProfileYesMain response provider and execution profile
FieldTypeRequiredDefaultDescription
system_promptstringNoJinja2 template used as the system prompt
prompt_clausesobjectNoNamed sections appended to the system prompt
knowledge_baseKnowledgeBase[]NoVector-search or direct-access knowledge sources
short_term_memory_strategyobject[]NoToken-based history trimming
long_term_memory_strategyobject[]NoContext flush strategies
evaluation_strategyobjectNoone-shootTool use and termination policy
toolsToolConfig[]NoExternal tool sources
persistence_strategy"INCREMENTAL" | "FLUSH" | "EPHEMERAL"No"INCREMENTAL"How conversation history is persisted

shields is a map of classifier names to shield-config objects. Each shield runs before the main inference call. Agent-scoped shields operate on the user request; tool- and topic-scoped shields operate on tool outputs and retrieved knowledge chunks.

FieldTypeRequiredDefaultDescription
provider_id"shield-config"YesMust be shield-config
connectorobjectYesUnderlying classifier connector
action"observe" | "flag" | "block"No"observe"Action when threshold is crossed
thresholdnumberNo0.5Score threshold
target_labelstringNoOnly this predicted label triggers the action
fail_closedbooleanNofalseBlock on shield errors or timeouts
block_messagestringNoRefusal text used when blocking

Built-in prompt-injection detector:

{
"provider_id": "shield-config",
"connector": {
"provider_id": "alquimia/prompt-injection-detection",
"heuristic_weight": 0.3,
"base_classifier_score": 0.0
},
"action": "block",
"threshold": 0.5,
"fail_closed": true
}

External Hugging Face text-classification model:

{
"provider_id": "shield-config",
"connector": {
"provider_id": "huggingface/text-classification",
"url": "https://your-hf-endpoint.com",
"token": { "$secretRef": "SHIELDS_PROVIDER_API_KEY" },
"label_map": { "LABEL_0": "safe", "LABEL_1": "toxic" }
},
"action": "block",
"threshold": 0.8,
"target_label": "toxic",
"block_message": "This request violates our safety policy."
}

LLM-based classifier using a registered model:

{
"provider_id": "shield-config",
"connector": {
"provider_id": "alquimia",
"profile": {
"system_prompt": "Classify user intent as one of: support, sales, enterprise.",
"evaluation_strategy": {
"evaluation_strategy_id": "one-shoot",
"structured_output": {
"method": "json_schema",
"json_schema": {
"type": "object",
"properties": { "intent": { "type": "string" } },
"required": ["intent"]
}
}
}
},
"config": { "model_ref": "gpt-4o-mini-classifier" }
},
"action": "observe"
}

See Shields & empathy for the conceptual model and How to configure content shields for step-by-step instructions.

empathy.rules is a list of conditional profile overrides evaluated after all shields run. The first matching rule is applied.

FieldTypeRequiredDescription
rule_idstringYesUnique rule identifier
strategy"none" | "override" | "merge"YesHow the rule changes the response profile
descriptionstringNoHuman-readable explanation
requirementsstring[]YesShield IDs that must be present for the rule to run
conditionsstring[]Yessimpleeval expressions; all must be true
responseResponseProfileYesProfile to apply (override) or merge
StrategyBehavior
noneNo-op
overrideReplace the entire response profile with response
mergeDeep-merge response into the main profile
{
"empathy": {
"rules": [
{
"rule_id": "toxic-input",
"strategy": "override",
"description": "Refuse toxic requests",
"requirements": ["toxicity"],
"conditions": ["toxicity['label'] == 'toxic'"],
"response": {
"provider_id": "fixed",
"message": "I'm sorry, I can't help with that."
}
},
{
"rule_id": "formal-enterprise",
"strategy": "merge",
"description": "Use formal tone for enterprise intent",
"requirements": ["intent-classifier"],
"conditions": ["intent-classifier.get('intent') == 'enterprise'"],
"response": {
"provider_id": "alquimia",
"profile": {
"prompt_clauses": {
"tone": "Use formal, professional language. Avoid contractions."
}
}
}
}
]
}
}

The config section inside response declares the LLM connector.

{
"provider_id": "openai",
"params": {
"model": "gpt-4o",
"temperature": 0.2,
"max_tokens": 2048,
"api_key": { "$secretRef": "RESPONSE_PROVIDER_API_KEY" },
"base_url": { "$secretRef": "RESPONSE_PROVIDER_BASE_URL" }
}
}
{
"provider_id": "groq",
"params": {
"model": "llama-3.3-70b-versatile",
"temperature": 0.1,
"groq_api_key": { "$secretRef": "RESPONSE_PROVIDER_API_KEY" }
}
}
{
"provider_id": "huggingface",
"params": {
"model": "meta-llama/Llama-3.1-8B-Instruct",
"api_key": { "$secretRef": "RESPONSE_PROVIDER_API_KEY" },
"base_url": { "$secretRef": "RESPONSE_PROVIDER_BASE_URL" }
}
}
FieldTypeDescription
modelstringModel identifier
temperaturenumberSampling temperature
max_tokensintegerMax output tokens
timeoutintegerRequest timeout in seconds
top_pnumberTop-p sampling
max_retriesintegerRetry count on failure
api_keySecretRefAPI key for OpenAI or Hugging Face
groq_api_keySecretRefAPI key for Groq
base_urlSecretRefCustom endpoint URL
organizationstringOpenAI organization ID
reasoning_formatstringReasoning format hint
reasoning_effortstringReasoning effort level
{
"provider_id": "fixed",
"message": "This is a fixed response for testing.",
"chunk_size": 64
}

Instead of embedding a model connector in every profile, you can reference a model registered in the registry:

Terminal window
alquimia registry models add gpt-4o-mini \
--provider-id openai \
--params '{"model": "gpt-4o-mini", "temperature": 0.0, "api_key": {"$secretRef": "RESPONSE_PROVIDER_API_KEY"}}'

Then use model_ref in response.config or inside a shield connector:

{
"response": {
"provider_id": "alquimia",
"config": { "model_ref": "gpt-4o-mini" },
"profile": {
"system_prompt": "You are a helpful assistant.",
"evaluation_strategy": { "evaluation_strategy_id": "one-shoot" }
}
}
}

Per-use params in the agent spec or shield override the registered model defaults.

Sensitive values are never stored in the agent spec. Declare them with $secretRef and resolve them at inference time.

{
"api_key": { "$secretRef": "RESPONSE_PROVIDER_API_KEY" }
}
ScopeEnvironment key formatVault path
globalKEYglobal/KEY
shared{REALM}_{KEY}{realm}/shared/KEY
local{REALM}_{ASSISTANT_ID}_{KEY}{realm}/local/{assistant_id}/KEY

REALM is the agentspace_id.

dtypeFormatExample
strRaw stringsk-abc123
booltrue/false, 1/0, yes/no, on/offtrue
intInteger string587
floatFloat string0.7
listJSON array or comma-separated["a","b"] or a,b

See Rotate secrets and Vault policies for operational details.

Single LLM call, no tools. Use for simple Q&A agents.

{
"evaluation_strategy_id": "one-shoot"
}

Native function calling for agents that use tools.

{
"evaluation_strategy_id": "native",
"max_steps": 10,
"max_concurrent_tools": 1,
"tool_choice": "auto",
"decorators": null,
"structured_output": null
}
FieldTypeDefaultDescription
max_stepsinteger10Max LLM calls before termination
max_concurrent_toolsinteger1Max tool calls per step
tool_choicestring or object"auto"Tool selection mode
decoratorsDecorator[]nullplan-mode and skills decorators
structured_outputobjectnullForce structured JSON output

Parse tool calls from unstructured text for models without native function calling.

{
"evaluation_strategy_id": "raw",
"max_steps": 10,
"max_concurrent_tools": 5,
"parse_regex_pattern": "\\{\\s*\"name\"\\s*:..."
}

Trims conversation history to stay within a token budget.

{
"short_term_memory_strategy": [
{
"memory_strategy_id": "max_tokens",
"memory_max_tokens": 10000,
"conditions": []
}
]
}
FieldTypeDefaultDescription
memory_max_tokensinteger10000Token budget; -1 disables trimming
conditionsstring[][]Empathy-style conditions

Triggers a context flush when thresholds are exceeded.

{
"long_term_memory_strategy": [
{
"long_term_memory_id": "summarizer",
"interaction_threshold_qty": 20,
"interaction_threshold_tokens": 20000,
"interaction_keep": 3,
"cod_max_loops": 5,
"instructions": "Focus on decisions and action items."
}
]
}
FieldTypeDefaultDescription
interaction_threshold_qtyinteger20Flush after this many interactions
interaction_threshold_tokensinteger20000Flush after this many tokens
input_tokens_thresholdinteger0Flush when LLM reports this many input tokens
interaction_keepinteger0Human turns to keep after flush
step_keep_qtyinteger0Trailing tool-call round trips to keep
step_keep_tokensinteger0Same as above, bounded by token budget
cod_max_loopsinteger5Chain-of-Density summarization iterations
instructionsstringSummarization focus instructions
knowledge_baseobjectStore summary in this knowledge base

Erases memory beyond retained interactions without summarization.

{
"long_term_memory_strategy": [
{
"long_term_memory_id": "neuralyzer",
"interaction_threshold_qty": 10,
"interaction_keep": 2
}
]
}

Decorators augment native evaluation with extra tools and prompt clauses.

Injects plan-management tools and a planning instruction block.

{
"decorator_id": "plan-mode",
"force_completion": false
}
FieldTypeDefaultDescription
force_completionbooleanfalseAgent must resolve all tasks before answering

Injected tools: create_plan, get_current_plan, mark_done, mark_failed, mark_blocked, mark_pending, add_task, add_note, rename_task.

Loads MDX skill documents and exposes tools to browse and activate them.

{
"decorator_id": "skills",
"skills_dir": "/app/skills"
}
FieldTypeRequiredDescription
skills_dirstringYesPath to directory containing .mdx skill files

Injected tools: list_skills, get_skill, select_skill, deselect_skill.

{
"provider_id": "whatsapp",
"channel_id": "whatsapp-main",
"template": "{{answer}}",
"middleware": [],
"whatsapp_assistant_phone_number_id": { "$secretRef": "WHATSAPP_PHONE_NUMBER_ID" },
"whatsapp_verify_token": { "$secretRef": "WHATSAPP_VERIFY_TOKEN" },
"whatsapp_access_token": { "$secretRef": "WHATSAPP_ACCESS_TOKEN" },
"whatsapp_api_base_url": { "$secretRef": "WHATSAPP_API_BASE_URL" }
}
{
"provider_id": "email",
"channel_id": "email-support",
"read_mailbox": "inbox",
"email_select_status": "UNSEEN",
"template": "<html><body>{{ answer | markdown_to_html }}</body></html>",
"middleware": [],
"email_username": { "$secretRef": "EMAIL_USERNAME" },
"email_password": { "$secretRef": "EMAIL_PASSWORD" },
"email_smtp_server": { "$secretRef": "EMAIL_SMTP_SERVER" },
"email_imap_server": { "$secretRef": "EMAIL_IMAP_SERVER" }
}
FieldTypeDefaultDescription
read_mailboxstring"inbox"IMAP mailbox to poll
email_select_statusstring"UNSEEN"IMAP search criteria
flag_on_readstring"(\\Seen)"Flag set when message is read
unflag_on_errorstring"(\\Seen)"Flag removed on processing error
templatestringJinja2 template for outbound HTML email
{
"provider_id": "slack",
"channel_id": "slack-main",
"template": "{{answer}}",
"middleware": [],
"slack_access_token": { "$secretRef": "SLACK_ACCESS_TOKEN" }
}
{
"middleware": [
{
"provider_id": "alquimia:whitelist",
"allowed_ids": { "$secretRef": "WHITELIST_MIDDLEWARE_ALLOWED_IDS" }
}
]
}

WHITELIST_MIDDLEWARE_ALLOWED_IDS must be a list dtype secret. Use "*" to allow all users.

{
"middleware": [
{
"provider_id": "cognito:otp",
"user_pool_id": { "$secretRef": "AWS_COGNITO_USER_POOL_ID" },
"client_id": { "$secretRef": "AWS_COGNITO_CLIENT_ID" },
"client_secret": { "$secretRef": "AWS_COGNITO_CLIENT_SECRET" },
"otp_regex": "\\b(\\d{6})\\b",
"otp_message": "Please send your 6-digit authentication code."
}
]
}

Requires the AWS extra and a Redis instance.

HTTP transport:

{
"provider_id": "mcp",
"tools_id": "filesystem-tools",
"human_approval": "NONE",
"url": { "$secretRef": "MCP_PROVIDER_URL" },
"auth": { "$secretRef": "MCP_PROVIDER_AUTH" },
"transport": "streamable-http"
}

Stdio transport:

{
"provider_id": "mcp",
"tools_id": "shell-tools",
"human_approval": "REQUIRED",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
"transport": "stdio"
}
FieldTypeRequiredDescription
tools_idstringNoUnique identifier for this tool source
human_approval"NONE" | "REQUIRED"NoLegacy approval gate
urlSecretRef or stringNoMCP server URL
authSecretRef or stringNoBearer token or auth method
commandstringNoCommand to launch for stdio transport
argsstring[]NoArguments for stdio command
envobjectNoEnvironment variables for stdio command
headersobjectNoHTTP headers
transportstringNoTransport type hint
{
"provider_id": "llama-stack",
"tools_id": "llama-tools",
"human_approval": "NONE",
"tool_group_id": "my-tool-group",
"authorization": { "$secretRef": "LLAMA_STACK_PROVIDER_AUTHORIZATION" }
}

Requires LLAMA_STACK_BASE_URL and LLAMA_STACK_API_KEY environment variables.

{
"provider_id": "a2a",
"tools_id": "specialist-agents",
"human_approval": "NONE",
"selector": { "tags": ["specialist"] },
"context": null
}
FieldTypeRequiredDescription
selectorobjectYesRegistry query to find agents
contextobjectNoExtra context passed to discovered agents

Agent specs may reference a registered tool by tool_ref instead of embedding raw connection config.

{
"provider_id": "mcp",
"tool_ref": "filesystem-tools",
"human_approval": "NONE"
}

The registry must contain a matching ToolRegistration. Inline fields override registry values. For bundled connections, classify individual operations by severity, tier grants, and approval.

FieldTypeRequiredDescription
tool_refstringYesregistered_tool_id to look up
tier_ceilingstring[]NoNarrows registry tier_grants for this agent (intersection)
human_approval"NONE" | "REQUIRED"NoLegacy approval gate

tier_ceiling intersects with the registry grants; it can never widen them.

SeverityMax grantable tierApproval
read-onlyreader, editor, operatorAs configured
mutating-recoverableeditor, operatorAs configured
destructiveoperator onlyAlways required

A tool name matching no classified operation is denied outright.

ValueBehavior
"NONE"Tool executes immediately unless the global authorization policy denies it
"REQUIRED"Emits a human-approval event before execution

A KnowledgeBase pairs a topic or collection with a consumption mode. It is safer to reference a registered topic by topic_id than to embed a raw collection_id, because the registry can enforce access policy and namespacing.

FieldTypeRequiredDescription
topic_idstringNoReference to a TopicRegistration in the registry
collection_idstringNoRaw vector collection name (use only in dev/tests)
descriptionstringNoDescription used by the model
search_modestringYesrag, on_demand, direct, or brain
search_typestringNosimilarity, mmr, or similarity_score_threshold
search_kwargsobjectNoProvider-specific search arguments
connectorobjectNoKnowledge provider connector; omitted for direct and brain
tier_ceilingstring[]NoNarrows the topic’s tier_grants for this agent (intersection)

When topic_id is set, the runtime resolves agentspace_id, external_collection_id, and the topic’s access_policy from the registry. The effective collection name is {agentspace_id}__{collection_id} and an agentspace_id metadata filter is injected into every query.

{
"collection_id": "product-docs",
"description": "Product documentation and FAQs",
"search_mode": "on_demand",
"search_type": "similarity",
"search_kwargs": { "k": 4 },
"connector": { "provider_id": "qdrant" }
}
{
"collection_id": "session-context",
"search_mode": "rag",
"search_kwargs": { "k": 4 },
"connector": { "provider_id": "redis", "ttl": 600 }
}
{
"collection_id": "upload-context",
"search_mode": "on_demand",
"search_kwargs": { "k": 4 },
"connector": { "provider_id": "in_memory" }
}
ValueBehaviorConnector
ragSearched automatically before each LLM callRequired
on_demandExposed as a search tool the agent calls explicitlyRequired
directExposes list_files/read_file tools over a registered topic; no connectorRequires topic_id
brainQueries a registered Boltzmann BrainMust be unset
FieldTypeDefaultDescription
kinteger4Number of results
score_thresholdnumberMinimum similarity score
fetch_kintegerDocuments to fetch before MMR filtering
lambda_multnumberMMR diversity vs relevance
filterobjectMetadata filters

search_mode: "direct" exposes list_files and read_file tools over a registered topic’s files. The agent can browse and read files directly instead of relying on vector search. The topic’s access_policy is enforced by the KnowledgeAuthzPolicy, so direct mode is not a bypass.

{
"topic_id": "product-docs",
"search_mode": "direct",
"tier_ceiling": ["reader", "editor"]
}
  • connector must be omitted.
  • Files must be uploaded and associated with the topic via the runtime API or CLI.
  • Use tier_ceiling to narrow the registry’s tier_grants for this agent.

See How to ingest files into a topic for upload and association steps.

{
"search_mode": "brain",
"brain_ref": "fourier-signals",
"modules": ["semantic", "procedural"]
}
FieldTypeDescription
brain_refstringbrain_id of a registered brain
modulesstring[]Memory modules to query

See Memory & context and Tools & integrations for conceptual overviews.