Agents
The portable definition of an Agent: every field, its tool bindings and its config.
An Agent definition is one YAML file per Agent, in agents/. To see a complete, valid project whose
Agent binds an MCP Tool, an OpenAPI Tool, a Knowledge Base and a Data Table, run
npx @elizon/cli example agent (offline, no account).
name: Specialist
description: 'Answers the request once it is well understood.'
status: active
configSchemaVersion: 1
llm:
slot: reasoning
modelPreference: null
tools: []
config:
basic:
include_agent_name: true
include_datetime: false
model:
primary:
llm_slot: reasoning
model_id: null
temperature: 0.7
max_output_tokens: 4096
secondary:
enabled: false
llm_slot: null
model_id: null
temperature: 0.7
max_output_tokens: 4096
memory:
enable_user_memory: false
enable_agentic_memory: false
session:
add_history_to_context: true
history_runs: 3
read_chat_history: true
session_summary: false
session_state: false
session_state_schema: null
instructions:
content: |
You answer the request that intake has clarified.
Be specific, and say when you are not sure.
knowledge:
agentic_rag: true
metadata_filter: false
knowledge_bases: []
reasoning:
mode: 'off'
effort: medium
max_steps: 5
expose: internal
advanced:
enable_markdown: true
enable_structured_output: false
structured_output_schema: null
retries: 0
retry_delay_seconds: 1
exponential_backoff: false
enable_tracking: true
enable_logging: trueThe fields that matter most
| Field | Meaning |
|---|---|
name, description | Display name and description of the Agent once installed. The manifest-local name is set in the manifest, not here. |
status | active for an Agent that should run. See status for draft and archived. |
configSchemaVersion | 1. |
llm.slot | The llm Slot the Agent thinks with. |
config.model.primary.llm_slot | The same Slot for the primary model, with generation settings (temperature, max_output_tokens). model_id: null lets the installer's LLM Configuration decide the model. |
config.model.secondary | An optional fallback model on another Slot. |
config.instructions.content | The system instructions. The biggest single factor in how the Agent behaves. |
tools | What the Agent may call: Tool operations, app operations and Data Table actions. See Tool bindings. |
skills | The Skills of this Package the Agent uses, as skills.<name> references. Install attaches them. See Skills. |
config.knowledge.knowledge_bases | Knowledge Bases the Agent answers from, as knowledgeBases.<name> references. |
config.memory | User and agentic memory, and how much conversation history is kept in context. |
config.reasoning | Reasoning mode (off, native or scratchpad), effort and step limit. |
config.advanced | Markdown, structured output, retries, tracking and logging. |
The settings correspond to the Agent editor in Studio. Everything is carried except what identifies an Organization: model ids come from the installer's Slot, and Tools and Knowledge Bases are wired to the resources the same install creates. Every field is described below.
Top-level fields
| Field | Valid values | What it does |
|---|---|---|
name | 1 to 128 characters | The installed Agent's display name. The operator can rename it at install. |
description | Text, or null | The installed Agent's description. |
status | draft, active, archived | See status. |
configSchemaVersion | 1 | The version of the config block's shape. This platform understands 1; any other number is refused before anything else is checked, because the platform cannot read a config written for a version it does not know. |
llm | An object, or null | The Agent's model Slot. |
llm.slot | The id of an llm Slot in elizon.yaml | The Slot the operator answers with one of their LLM Configurations at install. Use the same Slot as config.model.primary.llm_slot, as every example does. |
llm.modelPreference | A model id, or null | The model you would choose. It is used when the Configuration the operator picks offers it and it generates text; otherwise that Configuration's first text-generation model is. null means no preference. A Configuration that offers only embedding models is refused at install. |
tools | A list, [] for none | The Agent's tool bindings. See Tool bindings. |
skills | A list of skills.<name>; optional | The Skills the Agent uses. Leaving it out is the same as []. See Skills. |
config | An object | Everything the Agent editor in Studio sets. See The config block. |
status
Install creates the Agent with the status you write, and nothing in the install changes it.
status | What the installed Agent is |
|---|---|
draft | Installed but not published: it is not offered in a Workflow's AI Agent node until someone with permission to publish Agents activates it in Studio. |
active | Published. It can be picked in a Workflow's AI Agent node in Studio. Use this for every Agent the Package runs. |
archived | Installed as retired: not offered in a Workflow's AI Agent node, and a Team that lists it as a member shows it as stale. Useful only for an Agent you ship for reference. |
Tool bindings
tools: lists what the Agent may call. Each entry is one binding: one operation of one thing.
There are four kinds, and the keys tell them apart: a binding has tool, app or table, never
two of them.
| Kind | Keys | Stored as tool type | More |
|---|---|---|---|
| An MCP Tool's tool | tool, toolType: mcp, actionId, enabled, config | mcp | Tools → MCP |
| An OpenAPI Tool's operation | tool, toolType: swagger, actionId, enabled, config | swagger | Tools → OpenAPI |
| An app operation (Google apps) | app, resource, operation, credential, enabled, config | app | App operations |
| A Data Table action | table, actionId, enabled, config | data_table | Data Table actions |
toolType is written only on a Tool binding, and only as mcp or swagger. The installed binding's
tool type is app for an app operation and data_table for a Data Table action, but you never write
those: a binding with toolType: app or toolType: data_table is refused by build.
Every binding has:
enabled(trueorfalse, required):falsetravels as written, so the installed Agent has the binding switched off until the operator turns it on in Studio.config(required,{}for nothing): see Bindingconfig.
MCP and OpenAPI operations
tools:
# An MCP tool, named exactly as the server lists it.
- tool: tools.calendar
toolType: mcp
actionId: list_availability
enabled: true
config: {}
# An OpenAPI operation, named by its operationId in the spec.
- tool: tools.orders
toolType: swagger
actionId: getOrder
enabled: true
config: {}| Field | Valid values | What it does |
|---|---|---|
tool | tools.<name>, a tools: entry in elizon.yaml | Which Tool. The install creates the Tool first and binds the Agent to it. |
toolType | mcp, swagger | The Tool's kind. It must match the Tool file's own toolType; a mismatch is refused at install. |
actionId | 1 to 200 characters | MCP: the name of a tool the server lists. build never connects to the server, so it cannot check this name. OpenAPI: the operation's operationId (or its derived actionId); build writes the derived actionId into the artifact and refuses a name the spec does not have. |
Bind the same Tool once per operation the Agent should have. Two bindings of the same Tool and
actionId are refused (duplicate binding). The Tool file formats, and how build derives an
OpenAPI actionId, are on Tools.
App operations
An app operation is one operation of an app ELIZON ships (Google Calendar, Google Contacts, Google Drive, Google Sheets, Gmail), run as the operator's own connected account.
tools:
- app: google-calendar
resource: availability
operation: free-busy
credential: calendar-account
enabled: true
config:
param_overrides:
# The model cannot choose another calendar: this value always wins.
- name: calendarIds
value: [primary]compliance:
providers: [google]
slots:
- id: calendar-account
type: credential
scheme: oauth2
app: google
required: true
description: The Google account whose calendar the Agent reads.| Field | Valid values | What it does |
|---|---|---|
app | An app id (google-calendar, never the account's app google) | Which app. |
resource | A resource id of that app (availability, event, …) | Which part of the app. |
operation | An operation id of that resource (free-busy, list, …) | Which operation. An app or operation this ELIZON does not have is refused at install. |
credential | The id of a credential Slot, or null | The account the operation runs as. The Slot needs app: set to the app's account app (google), or validate refuses it. |
Rules that apply at install:
credential: null, or a Slot the operator leaves for later: the Agent is installed without this tool. Nothing fails; the Package's page lists the open Slot.- A Slot bound to a vault secret instead of a connected account is refused: an app operation runs as an account.
- Gmail is offered only on an ELIZON whose operator has turned it on; elsewhere the install is refused.
- An operation that answers with a file, or needs a file, cannot be an Agent tool: use it in a Workflow.
- List the app's provider (
google) incompliance.providers.validatewarns when it is missing. - An operation that cannot be undone (deleting an event) tells the model so in its description,
and a
description_overridecannot remove that sentence.
Two bindings of the same operation through the same credential Slot are refused; the same operation
through two different Slots is two accounts and is allowed.
Data Table actions
A Data Table binding gives the Agent one action on one of the Package's tables.
tools:
# Reads.
- table: dataTables.customers
actionId: rows.get
enabled: true
config: {}
- table: dataTables.customers
actionId: rows.exists
enabled: true
config: {}
- table: dataTables.customers
actionId: rows.lookup
enabled: true
config: {}
# Writes. Each one is a separate decision.
- table: dataTables.customers
actionId: rows.insert
enabled: true
config: {}
- table: dataTables.customers
actionId: rows.update
enabled: true
config: {}
- table: dataTables.customers
actionId: rows.upsert
enabled: false
config:
description_override: Records a customer, adding the row if the customer number is new.| Field | Valid values | What it does |
|---|---|---|
table | dataTables.<name>, a dataTables: entry in elizon.yaml | Which table. The install creates it first. |
actionId | rows.get, rows.exists, rows.lookup, rows.insert, rows.update, rows.upsert | What the Agent may do with it. |
actionId | What the Agent can do |
|---|---|
rows.get | Read rows with conditions, ordering and paging. A read. |
rows.exists | Ask whether any row matches, and how many. A read. |
rows.lookup | Give one key column and a list of values; get the matching rows per value. A read. |
rows.insert | Add new rows. Writes data. |
rows.update | Change the rows that match conditions. Writes data. |
rows.upsert | Change the rows that match, or add one when none do. Writes data. |
The opt-in rules:
- One table and one action per binding. Bind a table once per action the Agent should have.
- A write needs its own binding. The Agent can write only through an enabled binding for exactly that table and that action; a read binding never lets it write.
- There is no delete. A binding that names any other
actionIdis refused bybuild, at install, and again when the Agent calls it. To delete rows, use a Workflow's Data Table node. - A write tells the model it changes data, and a
description_overridecannot remove that.
The per-call bounds (rows returned, values looked up, rows written) and what each action answers are on Data Tables → Agent tool bindings.
Binding config
Every binding's config takes the same three keys, all optional. {} sets none of them.
| Key | Valid values | What it does |
|---|---|---|
description_override | Text, or null | Replaces the description the model sees for this tool. A sentence the platform adds for a write or an operation that cannot be undone stays. |
param_overrides | A list of { name, value } | Pins parameters. A pinned value always wins over the model's: whatever the model sends for that parameter, the pinned value is the one used. |
param_overrides[].name | A parameter name of the operation | The parameter to pin. |
param_overrides[].value | Any YAML value (text, number, list, object) | The value it always has. |
expose_to_scripts | true or false | Data Table bindings only: also mounts the whole table in the Agent's skill scripts as a file. See Skill scripts. |
tools:
- tool: tools.orders
toolType: swagger
actionId: listOrders
enabled: true
config:
description_override: Lists the open orders. Use it before you promise a delivery date.
param_overrides:
- name: status
value: openAny other key in config is refused by build.
Skills
skills: lists the Skills the Agent uses, each as skills.<name>, where <name> is a skills[]
entry in the same elizon.yaml. Install attaches each one to the Agent, as the Agent's Skills
section in Studio does. Leave the key out, or write [], for an Agent that uses none.
skills:
- skills.price-calculation- A name the manifest does not declare is refused by
validateandbuild:`agents.price-assistant` references `skills.nope`, which is not declared in this Package. - Each entry must be
skills.<name>. A bare name, another collection (tools.x) or the same Skill twice is refused bybuild. - Only a Skill of the same Package can be listed. An Organization's own Skills cannot be referenced.
- An Agent that lists Skills needs
compatibility.minPlatformVersion: 0.25.0or newer inelizon.yaml.validateandbuildrefuse a lower value. See Package manifest. - Exporting an Agent from Studio writes only the attached Skills that are in the same export. An
attached Skill left out of the export is left out of
skillstoo, without a warning: the Agent then ships without it. - When the operator installs onto one of their own Agents instead of the Package's, install adds the listed Skills to that Agent, and uninstalling removes only the attachments the install added. Skills the operator had already attached stay.
- An update attaches the Skills the new version lists, and uninstalling the Package removes the Agent's attachments with the Agent.
- The installed Skill is a draft: the operator activates it in Studio (after the scan, and the approval if it asks for tools) before the Agent can load it. See Skills.
Name the Skill in the Agent's instructions too, so the Agent knows when to use it.
The config block
config is what the Agent editor in Studio sets, field by field. Write every section, as the
examples do: install creates the Agent with the config you wrote and does not fill in a section you
left out. build checks every value you write against the rules Studio saves an Agent under, so a
value Studio would refuse (reasoning.max_steps: 40) is refused at build, not after install.
The Default column is what a new Agent gets in Studio, a reasonable starting value.
Three names differ from the stored Agent, because the stored ones identify the source
Organization: the portable model.primary.llm_slot and model.secondary.llm_slot are stored as
llm_config_id (the operator's Configuration, resolved at install); a Knowledge Base binding's
knowledge_base is stored as kb_id plus the installed Knowledge Base's name; and
instructions.template_id (a pointer into the source Organization's prompt library) is never
carried, because the template's text is already in instructions.content. Write the portable names.
basic
| Field | Valid values | Default | What it does |
|---|---|---|---|
basic.include_agent_name | true or false | true | Adds the Agent's name to its context. |
basic.include_datetime | true or false | false | Adds the current date and time (UTC) to its context. |
model
| Field | Valid values | Default | What it does |
|---|---|---|---|
model.primary.llm_slot | The id of an llm Slot | — | Required. The Slot the primary model comes from. |
model.primary.model_id | A model id, or null | null | A preference, chosen as llm.modelPreference is: used when the operator's Configuration offers it, otherwise that Configuration's first text model. |
model.primary.temperature | 0 to 2 | 0.7 | Sampling temperature. |
model.primary.max_output_tokens | A whole number above 0 | 4096 | The most tokens one answer may have. |
model.secondary.enabled | true or false | false | Turns on the fallback model. It is used only if the primary model fails during a run. |
model.secondary.llm_slot | The id of an llm Slot, or null | null | The Slot the fallback comes from. A different provider gives real failover. |
model.secondary.model_id | A model id, or null | null | As model.primary.model_id. |
model.secondary.temperature | 0 to 2 | 0.7 | As model.primary.temperature. |
model.secondary.max_output_tokens | A whole number above 0 | 4096 | As model.primary.max_output_tokens. |
memory
| Field | Valid values | Default | What it does |
|---|---|---|---|
memory.enable_user_memory | true or false | false | Memories about the user, shared with other Agents for the same user, across sessions. |
memory.enable_agentic_memory | true or false | false | Gives the Agent tools to manage those memories itself. |
memory.session.add_history_to_context | true or false | true | Puts earlier messages of the current session in the Agent's context. |
memory.session.history_runs | A whole number, 0 or more | 5 | How many earlier runs of the session that history covers. |
memory.session.read_chat_history | true or false | false | Gives the Agent a tool to fetch older messages of the session. |
memory.session.session_summary | true or false | false | Keeps a condensed summary of the conversation. |
memory.session.session_state | true or false | false | Studio's "Session state" switch. Carried and shown in Studio; the runtime does not act on it yet. |
memory.session.session_state_schema | A JSON Schema, or null | null | The schema for that state. Carried as written. |
instructions
| Field | Valid values | Default | What it does |
|---|---|---|---|
instructions.content | Text | '' | The system instructions. Write them as a YAML block (content: |). |
knowledge
| Field | Valid values | Default | What it does |
|---|---|---|---|
knowledge.agentic_rag | true or false | true | true: the Agent gets one search tool per Knowledge Base and decides when to search. false: relevant passages are retrieved and added to every run's context. |
knowledge.metadata_filter | true or false | false | Lets the Agent filter a search on the Knowledge Base's metadata fields when its instructions say to. |
knowledge.knowledge_bases | A list, [] for none | [] | The Knowledge Bases the Agent answers from. |
knowledge.knowledge_bases[].knowledge_base | knowledgeBases.<name>, a knowledgeBases: entry in elizon.yaml | — | Which Knowledge Base. Never a display name or an id. |
knowledge.knowledge_bases[].max_results | 1 to 50 | 10 | The most passages one search returns (Studio's default when you bind one). |
knowledge.knowledge_bases[].hyde_retrieval | true or false | false | Writes a hypothetical answer first and searches with it. Can find more, and is slower. |
config:
knowledge:
agentic_rag: true
metadata_filter: false
knowledge_bases:
- knowledge_base: knowledgeBases.product-docs
max_results: 5
hyde_retrieval: falsereasoning
| Field | Valid values | Default | What it does |
|---|---|---|---|
reasoning.mode | off, native, scratchpad | off | off: no reasoning is asked for. native: the model's own reasoning (choose a reasoning-capable model). scratchpad: the Agent gets a think-and-analyse tool, on any model. Quote it ('off'), as the examples do: an older (YAML 1.1) tool reads a bare off as false. |
reasoning.effort | low, medium, high | medium | How hard a native model reasons. |
reasoning.max_steps | 1 to 20 | 5 | scratchpad only: the most tool calls in one run. Every tool call counts, real tools included, not only the thinking steps. |
reasoning.expose | internal, operator | internal | operator shows the reasoning in the chat transcript; internal records it and hides it. |
How each mode behaves when the Agent also has tools (skills, Knowledge Bases, Tools):
offorscratchpad: if the model refuses tools because it reasons by default, the run is retried once without reasoning, and ELIZON remembers that for the model, so later runs send that setting from the start. A second refusal fails the run with the provider's message.nativeon OpenAI: the run uses OpenAI's Responses API, which accepts a reasoning effort and tools together. On any other provider, Azure OpenAI and OpenAI-compatible endpoints included, nothing changes.
advanced
| Field | Valid values | Default | What it does |
|---|---|---|---|
advanced.enable_markdown | true or false | false | Formats answers as Markdown. |
advanced.enable_structured_output | true or false | false | Makes the answer a JSON object that follows structured_output_schema, which a Workflow can then read field by field. |
advanced.structured_output_schema | A JSON Schema, or null | null | The schema the answer follows. Ignored when enable_structured_output is false, or when it is not a JSON object. |
advanced.retries | A whole number, 0 or more | 3 | How many times a failed run is retried. |
advanced.retry_delay_seconds | A number, 0 or more | 1 | Seconds between retries (whole seconds are used). |
advanced.exponential_backoff | true or false | false | Doubles the delay with each retry. |
advanced.enable_tracking | true or false | true | Studio's "Enable tracking" switch (execution traces). Carried and shown in Studio; the runtime does not act on it yet. |
advanced.enable_logging | true or false | true | Studio's "Enable logging" switch (the Logs view). Carried and shown in Studio; the runtime does not act on it yet. |
config:
advanced:
enable_markdown: false
enable_structured_output: true
structured_output_schema:
type: object
properties:
category: { type: string, enum: [billing, delivery, other] }
required: [category]
retries: 2
retry_delay_seconds: 2
exponential_backoff: true
enable_tracking: true
enable_logging: trueCombinations a provider can refuse
Some models reason by default, even with reasoning.mode: 'off', and their provider refuses
function tools unless it is told not to reason. Any Agent with tools (a Knowledge Base, a skill, a
Tool, an app operation or a Data Table action) can meet this. ELIZON retries such a run once and
remembers the model; native mode on OpenAI uses the Responses API instead. If it still fails, the
run ends with the provider's message, which reads like:
Function tools with reasoning_effort are not supported for <model> in /v1/chat/completions.
To use function tools, use /v1/responses or set reasoning_effort to 'none'.What happens in each mode, and why a streamed run (/run-stream) reports the first refusal as an
error event instead of retrying it, is in Agents → Reasoning and
tools. Nothing in the Package can prevent it: which
models reason by default is the provider's choice, so the fix, if one is needed, is the operator's
choice of model.
Wiring
- Reference the Agent elsewhere as
agents.<manifest-name>: in a Team's members, a Workflow'sai_agentnode, a voice configuration, or as the entry point. - Any Slot the Agent uses can list it in
boundTo, so the installer sees which answer affects it. - Install order guarantees the Agent's Tools, Skills, Knowledge Bases and Data Tables exist before the Agent does.