Skip to main content

Agent Definition Reference

An agent in Achilles is a single YAML document that describes who the agent is, which systems it can reach, who may do what, and when it must ask a person. Most customers never edit this file by hand: Agent Builder generates it from your procedures and database, and you refine it through the console.

Reach for the raw file when you want to review exactly what an agent is allowed to do (compliance teams often do), make a bulk change that is faster as text, keep a copy in your own version control, or move an agent between workspaces.

Import and export in the console​

Open the agent in the console and use the editor to view its YAML. Edit it in place and save, or use Import YAML to bring in a file. Every save is validated first: if something is wrong, you see the exact field and a plain message, and nothing is changed. Take a version snapshot before larger edits so you can compare and restore. To export, copy the YAML from the editor into your own repository.

The same checks run whether you save from the editor, the API, or Agent Builder. Beyond shape, they verify cross-references (every tool points at a real datasource, every role at real tools), row-filter coverage on database queries, and safe defaults for approvals and personal data.

Top-level fields​

FieldTypeRequiredDefaultDescription
appstringyesnoneDisplay name for labels and filenames. Operational API identity is embed_key (public name: agentKey), not this field. Minimum length 1.
versionpositive integeryesnoneDefinition version number.
tenantstringyesnoneTenant id. Copied into tokens and session records, and used to scope channels.
personaobjectyesnoneName, tone, and prompt-level behavior. See persona.
modelobjectnoprovider defaultsModel routing. See model.
datasourcesarrayyesnoneAt least one datasource. See datasources.
rolesmap of role key to objectyesnoneRoles and their tool access and row filters. See roles.
role_mappingmap of string to stringnononeMaps a host application's role names to role keys in roles.
toolsarrayyesnoneAt least one tool. See tools.
guardrailsobjectnosee guardrailsPlatform-level safety rules enforced in code.
fast_patharrayno[]Cheap routes that skip the full agentic loop.
evalsarrayno[]Test cases that run against the runtime.
voiceobjectnononeVoice channel configuration.
orchestrationobjectnononeStep limits, chain hints, and human handoff.

role_mapping values must be role keys defined under roles. Roles that are not mapped fall back to least privilege. See Role Mapping.

persona​

FieldTypeRequiredDefaultDescription
namestringyesnoneThe agent's display name.
tonestringyesnoneTone guidance, for example "friendly and concise".
languagestringnoen-hiLanguage hint.
refuse_outside_scopebooleannotrueWhether the agent declines requests outside its tools.
greetingstringnononeOpening message shown in a fresh session.
industryenumnononeConsole grouping for icons. One of travel, insurance, banking, healthcare, retail, support, sales, operations, general. Cosmetic only.
iconstringnononeIcon id from the console catalog. Cosmetic only.
icon_colorstringnononeChip color for the icon. Cosmetic only.
limitationsarray of stringno[]Refusal rules injected into the system prompt verbatim.
system_prompt_extrastringnononeExtra system prompt text.
system_promptstringnononeAccepted alias for system_prompt_extra. If both are set, system_prompt_extra wins.

limitations are prompt guidance, not a security boundary. Anything that must not happen belongs in guardrails or roles, which the model cannot talk its way past. See Guardrails.

model​

The whole block is optional. Omit it to use auto routing. See Model Routing.

FieldTypeRequiredDefaultDescription
providerenumnoautoOne of auto, anthropic, openrouter, ollama, ollama-local, sarvam, bedrock.
modelstringnoautoA plain model name, or provider:model for explicit routing.
max_tokensnumberno1024Maximum output tokens per model call.
temperaturenumber, 0 to 1no0.3Sampling temperature.
fast_modelstringnononeCheaper model for fast-path single-tool queries, for example ollama:gemma4:31b-cloud.

datasources​

An array with at least one entry. Datasource definitions never contain credentials. They name a credential, and the value is stored encrypted under Datasources in the console. See Datasources.

FieldTypeRequiredDefaultDescription
idstringyesnoneReferenced by tools[].datasource_id.
typeenumyesnoneOne of postgres, rest, mysql, mcp.
connection_envstringyesnoneEnvironment variable name. Must match ^[A-Z][A-Z0-9_]*$. Never the value.
base_url_envstringnononeFor rest: env var holding the base URL.
authenumnoservice_accountOne of bearer_passthrough, service_account, api_key.
mcpobjectrequired when type is mcpnoneSee below.

datasources[].mcp​

FieldTypeRequiredDefaultDescription
serverenumyesnoneachilles:db and achilles:email are first-party servers hosted in-process. remote is any third-party MCP server.
transportenumnostreamable_httpOnly streamable_http. Relevant to remote.
timeout_mspositive integerno15000Per-call timeout.
forward_contextbooleannofalseSend the signed Achilles context (identity and row scope) to a remote server. First-party servers always receive it.
token_envstringnononeremote: env var holding the bearer token.
from_envstringnononeachilles:email: env var holding the From address. Required for email.
reply_to_envstringnononeachilles:email: env var holding the Reply-To address.
allowed_recipient_domainsarray of stringno[]achilles:email: domains the connector may send to. Empty means any (the validator warns).
max_recipientspositive integerno5achilles:email: cap on to and cc recipients per send.

See Connectors and MCP.

roles​

roles is a map. Each key is a role name, and the value has the fields below.

FieldTypeRequiredDefaultDescription
row_filtersmap of string to stringno{}SQL predicates injected server-side. The default key applies to any table without its own entry. Values can interpolate identity claims such as {{user.customerId}}.
allowed_toolsarray of stringyesnoneAt least one entry. Tool ids the role may call.
deny_writebooleannofalseBlocks mutation tools for this role.

See Role Mapping and Guardrails.

tools​

An array with at least one entry. Which fields apply depends on type and on the datasource.

FieldTypeRequiredDefaultDescription
idstringyesnoneUnique tool id.
descriptionstringyesnoneWhat the tool does and when to use it. The model reads this to choose tools.
datasource_idstringyesnoneMust match a datasource id.
typeenumnoqueryquery, mutation, or dynamic_query.
sqlstringSQL toolsnoneTemplate with {{row_filter}} and $1, $2 placeholders. Not allowed on dynamic_query.
methodenumREST toolsnoneGET, POST, PUT, PATCH, or DELETE.
pathstringREST toolsnoneRequest path.
body_templatestringnononeREST body template.
mcp_toolstringMCP toolsnoneThe tool's name on the MCP server, for example query or send_email.
input_schemaobjectnononeThe server's JSON Schema for mcp_tool, pinned at discovery time. Has type (always object), properties (default {}), and optional required.
allowed_tablesarray of stringdynamic_querynoneTable allowlist the model may reference. Also required on MCP database tools.
unscoped_tablesarray of stringno[]dynamic_query: subset of allowed_tables that are shared catalogs and need no row filter.
denied_columnsarray of stringno[]dynamic_query: columns the model may never select, merged with a built-in denylist of secret-shaped names.
schema_hintstringnononedynamic_query: column and enum notes injected into the system prompt verbatim.
paramsmap of string to objectno{}Declared parameters. See below.
pii_fieldsarray of stringno[]Result fields to mask or hash. See PII Protection.
requires_confirmationbooleannofalseAsk the user to approve before the tool runs. See Confirmations.
max_rowsnumbernononePer-tool row cap.
returnsenumnoobjecttable, object, scalar, or void.
status_labelstring, max 80nononeEnd-user status line shown while the tool runs. Defaults to a generic line, never the tool id.
escalation_rulesarrayno[]Rules evaluated on the result to trigger human handoff.
chainable_toarray of stringno[]Tools expected to follow this one. Metadata only.

Dynamic query tools are covered in Dynamic Query Tools.

tools[].params​

params is a map from parameter name to an object.

FieldTypeRequiredDefaultDescription
typeenumyesnonestring, integer, number, boolean, or enum.
descriptionstringyesnoneShown to the model.
requiredbooleannofalseWhether the model must supply it.
defaultstring, number, or booleannononeValue used when omitted.
minnumbernononeLower bound for numbers.
maxnumbernononeUpper bound for numbers.
patternstringnononeRegular expression a string must match.
valuesarray of stringenum onlynoneAllowed values. The validator rejects an enum without them.

tools[].escalation_rules​

FieldTypeRequiredDefaultDescription
ifstringyesnoneA single condition in the form field OP value, for example premium_amount > 500000. Evaluated in code against the tool result.
flagstringnorequires_human_reviewThe flag set on a match. Matches the handoff trigger tool_result_flag.

guardrails​

Optional. If omitted, all defaults below apply. See Guardrails.

FieldTypeRequiredDefaultDescription
block_if_no_row_filterbooleannotrueRefuse to run a query for a role that has no row filter.
max_rowsnumberno50Global row cap.
deny_write_for_rolesarray of stringno[]Roles that may never run mutation tools.
mask_pii_unless_rolesarray of stringno[]Roles that see unmasked pii_fields. Everyone else sees masked values.
require_confirmation_for_mutationsbooleannotrueRequire user approval for every mutation.

fast_path​

An array of rules that route a matching question straight to one tool, skipping the full agentic loop. See Fast Path. Each rule accepts either of two shapes.

FieldTypeRequiredDescription
intentstringone of intent or intent_keywordsA phrase. It is split on whitespace into keywords.
intent_keywordsarray of stringone of intent or intent_keywordsExplicit keywords. Must be non-empty if used.
toolstringone of tool or tool_idTool id to run.
tool_idstringone of tool or tool_idAlias for tool.

The alias exists so definitions written against either spelling load unchanged. The same list may also be nested under orchestration.fast_path. If the top-level list is empty, the nested one is used.

evals​

An array of test cases. See Evaluation.

FieldTypeRequiredDefaultDescription
askstringyesnoneThe user message.
descriptionstringnononeLabel shown in reports.
rolestringnoleast privileged roleRun the case as this role. Must exist in roles.
expect_toolstringnononePasses when this tool is called. Must exist in tools.
expect_refusalbooleannononePasses when the reply is a refusal and no tool ran.
expect_containsstringnononePasses when the reply contains the string.
expect_handoffbooleannononePasses when the handoff outcome matches.

voice​

Optional. See Voice. If present, every field below has a default.

FieldTypeRequiredDefaultDescription
enabledbooleannofalseTurn the voice channel on.
modesarray of text or voiceno[text, voice]Modes the agent offers.
greetingstringnononeSpoken opening line.
sttobjectnosarvam, saaras:v3Speech-to-text config.
ttsobjectnosarvam, bulbul:v3, speaker priyaText-to-speech config.

voice.stt​

FieldTypeRequiredDefaultDescription
providerenumnosarvamsarvam or deepgram.
modelstringnosaaras:v3STT model.
languagestringnononeLanguage code.

voice.tts​

FieldTypeRequiredDefaultDescription
providerenumnosarvamsarvam, elevenlabs, or azure.
modelstringnobulbul:v3TTS model.
speakerstringnopriyaVoice name.

The validator warns when a provider is not implemented by the runtime.

orchestration​

Optional. See Orchestration and Handoff.

FieldTypeRequiredDefaultDescription
max_stepsinteger, 1 to 50noruntime defaultHard ceiling on agentic loop iterations.
pipeline_toolsarrayno[]Chain hints. Metadata only, not enforced.
handoffobjectnononeHuman handoff configuration.
fast_patharraynononeAccepted alias for the top-level fast_path.

orchestration.pipeline_tools[]​

FieldTypeRequiredDescription
idstringyesThe tool.
chainable_toarray of stringyesNon-empty list of tools expected to follow it.

Hints declared here and in tools[].chainable_to are merged.

orchestration.handoff​

FieldTypeRequiredDefaultDescription
enabledbooleannofalseTurn handoff on.
triggersobjectnosee belowWhat causes a handoff.
notify_channelenumnoemailemail, webhook, whatsapp, or slack.
notify_to_rolestringyesnoneA role key whose contact receives the notification.
agent_responsestringyesnoneMessage shown to the user. Supports the {{session_id}} and {{role}} placeholders.

orchestration.handoff.triggers​

FieldTypeRequiredDefaultDescription
phrase_matcharray of stringno[]Phrases in the user message that force a handoff.
tool_result_flagstringnorequires_human_reviewThe escalation flag that forces a handoff.
unresolved_turnspositive integerno3Consecutive turns of the same unresolved ask before handing off.

Full annotated example​

This is a complete, valid definition. It is a generic support agent and contains no credentials.

app: example-support # display name; API uses embed_key as agentKey
version: 1
tenant: example

persona:
name: Ava
tone: friendly and concise
language: en
refuse_outside_scope: true
greeting: "Hi, I'm Ava. Ask me about an order or a customer's support tickets."
industry: support # cosmetic
icon: headset # cosmetic
limitations: # prompt-level guidance, not a security boundary
- Read-only, never creates, updates, or deletes anything
system_prompt_extra: |
You help a support team look up orders and tickets. Always use the tools
to fetch exact values and never guess.

model:
provider: auto
model: auto
max_tokens: 512
temperature: 0.2

datasources:
- id: support_db
type: postgres
connection_env: EXAMPLE_SUPPORT_DB_URL # an env var NAME, never the value
auth: service_account

roles:
viewer:
row_filters:
default: '"customerId" = {{user.customerId}}' # injected server-side
allowed_tools: [get_order_status, list_customer_tickets]
agent:
row_filters:
default: 1=1
allowed_tools: ['*']

role_mapping: # host role -> agent role
VIEWER: viewer
SUPPORT_AGENT: agent

tools:
- id: get_order_status
description: Look up an order's fulfilment and payment status by order number.
datasource_id: support_db
type: query
params:
orderNumber:
type: string
description: The order number to look up
required: true
sql: |
SELECT "orderNumber", "customerId", "status", "paymentStatus"
FROM "Order"
WHERE {{row_filter}} AND "orderNumber" = $1
returns: table
pii_fields: [customerId]
status_label: Checking your order
chainable_to: [list_customer_tickets]

guardrails:
block_if_no_row_filter: true
max_rows: 50
require_confirmation_for_mutations: true
deny_write_for_roles: [viewer, agent]
mask_pii_unless_roles: [agent]

fast_path:
- intent: order status
tool: get_order_status

evals:
- description: Order status, happy path
ask: What's the status of order ORD-1001?
expect_tool: get_order_status
- description: Human handoff on complaint
ask: This is a complaint, I want to speak to a person
role: viewer
expect_handoff: true

voice:
enabled: false

orchestration:
max_steps: 6
handoff:
enabled: true
triggers:
phrase_match: [talk to a human, this is a complaint]
tool_result_flag: requires_human_review
unresolved_turns: 3
notify_channel: email
notify_to_role: agent
agent_response: >
I've passed this conversation to a support agent. Your reference number
is {{session_id}}.

Validate a definition before saving it by pasting it into the console editor, which checks it as you type, or by calling the validate endpoint in the API reference.