Skip to main content
Version: v2.0

Agent configuration

An agent's configuration is one JSON object, the agent template. It is stored on a workflow revision and travels on the wire at data.parameters.agent.

The schema is published as the catalog type agent-template. Fetch the live JSON Schema with:

GET /api/workflows/catalog/types/agent-template

The template rejects unknown keys. The harness, runner, and sandbox sub-objects also reject unknown keys at parse time and return HTTP 400.

For what these parts mean, see Agents, Instructions, Harnesses and models, and Permissions.

Top-level fields​

Every field is optional. An omitted field falls back to the default in the table.

FieldTypeRequiredDefaultDescription
instructionsobjectNo{"agents_md": "<built-in text>"}The agent's instruction documents.
llmobjectNosee llmThe model the agent runs on, its provider, and its credential connection.
toolsarrayNo[]Tools the agent can call. Each entry is one of the tool objects below.
mcpsarrayNo[]MCP servers exposed to the agent.
skillsarrayNo[]Skills the agent ships with.
harnessobjectNosee harnessThe coding agent to drive, plus its gating posture.
runnerobjectNosee runnerThe engine that drives the harness loop, plus the tool execution policy.
sandboxobjectNosee sandboxWhere the agent runs, plus its security boundary.

instructions​

FieldTypeRequiredDefaultDescription
agents_mdstringNoA built-in hello-world textThe agent's system prompt. The harness receives it as AGENTS.md.

llm​

FieldTypeRequiredDefaultDescription
modelstringNo"gpt-5.6-luna"Model id in the provider's namespace. A provider/model string also parses, split on the first /.
providerstring or nullNonullModel provider. When unset, resolution infers it from a matching stored connection, and fails with an error when it cannot.
connectionobject or nullNonullWhere the model credential comes from. Omit for the project default.
extrasobjectNo{}Model knobs passed through unchanged, for example reasoning_effort.

llm.connection​

FieldTypeRequiredDefaultDescription
mode"agenta" | "self_managed"No"agenta"agenta uses a connection stored in the project. self_managed injects no credential; the harness signs itself in.
slugstring or nullNonullThe named stored connection. Valid only with mode: "agenta". Omit for the project default. Setting it with self_managed is rejected.

Which providers, deployments, and connection modes each harness can reach is served per harness:

GET /api/workflows/catalog/harnesses/{harness}

In the shipped table, pi_core reaches openai, anthropic, gemini, mistral, groq, minimax, together_ai, and openrouter, with deployments direct and custom. claude reaches anthropic only, with deployments direct, custom, bedrock, and vertex_ai, and selects its model by alias rather than by a provider/model string.

tools​

Each entry in tools is an object discriminated by type. Code, client, and reference tools accept the shared fields below. A gateway_connection entry uses its own policy instead.

FieldTypeRequiredDefaultDescription
permission"allow" | "ask" | "deny" | nullNonullPer-tool override of the runner policy. Absent means inherit runner.permissions.default.
renderobject or nullNonullDisplay hint carried through to the client.

Harness built-ins​

Harness built-ins are always active. Do not list them in tools. Pi provides read, bash, edit, write, grep, find, and ls; the runner treats read, grep, find, and ls as read-only.

{"type": "builtin", "name": "read"} is a legacy shape. Agenta accepts and ignores it while older revisions migrate.

type: gateway_connection​

One connected application, including all actions that its integration advertises.

FieldTypeRequiredDefaultDescription
type"gateway_connection"Yes
connection.provider"composio"No"composio"Integration gateway.
connection.integrationstringYesConnected app key, such as github.
connection.slugstringYesExisting project connection slug.
policy.permissions.default"inherit" | "allow" | "ask" | "deny"No"inherit"Default for actions on this connection.
policy.permissions.toolsobjectNo{}Per-action decisions keyed by action name.
{
"type": "gateway_connection",
"connection": {
"provider": "composio",
"integration": "github",
"slug": "github-primary"
},
"policy": {
"permissions": {
"default": "allow",
"tools": { "DELETE_REPOSITORY": "deny" }
}
}
}

The connection slug must already exist. A second gateway_connection for the same provider and integration is rejected.

The per-action gateway shape is legacy. Preserve it when reading an older revision, but use gateway_connection for new configurations.

type: code​

A script the runner executes.

FieldTypeRequiredDefaultDescription
type"code"Yes
namestringYesModel-visible tool name.
descriptionstring or nullNonullWhat the tool does.
runtime"python" | "node"No"python"Script runtime.
scriptstringYesThe script source.
input_schemaobjectNo{"type": "object", "properties": {}}JSON Schema for the tool's arguments.
secretsarray of stringNo[]Names of secrets injected into the script's environment.

type: client​

A tool the calling client fulfils instead of the server.

FieldTypeRequiredDefaultDescription
type"client"Yes
namestringYesModel-visible tool name.
descriptionstring or nullNonullWhat the tool does.
input_schemaobjectNo{"type": "object", "properties": {}}JSON Schema for the tool's arguments.

type: reference​

Another workflow exposed to the agent as a tool. Agenta runs it server-side.

FieldTypeRequiredDefaultDescription
type"reference"Yes
ref_by"variant" | "environment"No"variant"Which axis selects the workflow revision.
slugstringYesThe workflow slug to reference.
environmentstring or nullNonullEnvironment slug. Required when ref_by is "environment", rejected otherwise.
versionstring or nullNonullPin a revision. Valid only with ref_by: "variant". Absent means the latest revision.
namestring or nullNonullLegacy display-name copy. It does not change the model-visible name.
descriptionstring or nullNonullWhat the tool does.
input_schemaobjectNo{"type": "object", "properties": {}}JSON Schema for the tool's arguments.

The workflow slug becomes the model-visible tool name.

Platform tools​

Agenta can inject platform operations such as discover_tools into a run. Do not add a type: "platform" entry to the stored template. The commit API rejects authored platform tools.

mcps​

Each entry declares one MCP server. See MCP servers for these fields in context, and Tools and integrations for the concept.

FieldTypeRequiredDefaultDescription
namestringYes1 to 128 characters matching ^[A-Za-z0-9._-]+$. The name agenta-tools is reserved and rejected. The harness renders this server's tools as mcp__<name>__<tool>, so it is frozen when the connection is chosen and renaming that connection does not change it.
connectionobjectYesWhich connection reaches the server. One of the two shapes below, selected by type.
policyobjectNo{"tools": {"mode": "all", "names": []}}Which of the server's tools are exposed, and at what permission.

mcps[].connection, gateway​

The shape the platform writes. The upstream URL and the credentials belong to the connection, so neither appears in the agent template.

FieldTypeRequiredDefaultDescription
type"gateway"Yes
namespace"custom" | "standard" | "builtin"Yescustom is a server connected in this project.
slugstringWith customThe connection's platform slug, derived once and never changed. Rejected with the other namespaces.
providerstringWith standard and builtinThe provider key. Rejected with custom.

An entry that carries no connection is matched to a connection by name. That fallback is deprecated and kept only for agent revisions committed before connections had an identity of their own.

mcps[].connection, direct HTTP​

Used where no gateway is configured, such as an SDK run outside the platform.

FieldTypeRequiredDefaultDescription
type"http"YesTransport.
urlstringYesThe server URL.
headersobject of stringNo{}Public request headers.
credentialsobjectNo{"type": "none"}Either {"type": "none"} or {"type": "header_secret_refs", "headers": {"<header>": "<secret-slug>"}}. Secret values resolve at run time and are never stored in the configuration.

A header name may not appear in both headers and credentials.headers. The comparison ignores case.

mcps[].policy​

FieldTypeRequiredDefaultDescription
tools.mode"all" | "include"No"all"all exposes every tool the server advertises. include exposes only tools.names.
tools.namesarray of stringNo[]Tool names as the server advertises them. Required with include, rejected with all.
permission"allow" | "ask" | "deny" | nullNonullPermission applied to this server's tools. Absent means inherit runner.permissions.default.
tool_permissionsobjectNo{}Per-tool permissions, keyed by the name the server advertises (echo), never the harness-rendered name (mcp__acme__echo).
new_tool_permission"allow" | "ask" | "deny"NounsetPermission for an advertised tool that tool_permissions does not name.

Setting either tool_permissions or new_tool_permission opts this server into per-tool policy. An advertised tool then resolves to its tool_permissions entry, and otherwise to new_tool_permission, which is ask when you leave it unset. Neither permission nor runner.permissions.default reaches a tool the table does not name, so nothing set elsewhere can widen the table. With both fields absent, the entry carries no per-tool policy and permission governs the whole server, exactly as before.

The permission editor writes new_tool_permission for you where the server is set to allow: giving one tool a rule of its own also records allow as the default for the tools you have not named, so those tools keep running as they did. Set the field yourself to choose a narrower default. Picking Ask for write and delete in that editor writes permission: "ask", an allow entry in tool_permissions for each tool the server marks read-only that the filter admits, and new_tool_permission: "ask".

tool_permissions may not name a tool that tools.mode: "include" hides. That configuration is rejected rather than silently dropped.

skills​

Each entry is an inline skill package. See Skills.

FieldTypeRequiredDefaultDescription
namestringYes1 to 64 characters matching ^[a-z0-9]+(-[a-z0-9]+)*$.
descriptionstringYes1 to 1024 characters. This is what the agent sees at the start of a session, and what decides when the skill loads.
bodystringYes1 to 50,000 characters. The skill's SKILL.md content after the frontmatter.
filesarrayNo[]Files laid beside SKILL.md.
disable_model_invocationbooleanNofalseHide the skill from the prompt so it loads only when invoked by name.
allow_executable_filesbooleanNofalseAllow bundled files to be marked executable. Sandbox policy must also allow it.

skills[].files[]​

FieldTypeRequiredDefaultDescription
pathstringYes1 to 255 characters. Relative POSIX path. A leading /, a backslash, a .. segment, or a root-level SKILL.md is rejected.
contentstringYesUTF-8 text, up to 200,000 characters.
executablebooleanNofalseMark the file executable when it is written out.

harness​

FieldTypeRequiredDefaultDescription
kind"pi_core" | "claude" | "codex"No"pi_core"Which coding agent to drive.
permissionsobjectNosee harness.permissionsTool-use gating posture, applied by harnesses that gate.
extrasobjectNo{}Per-harness knobs passed through unchanged. For Pi, system replaces the base system prompt and append_system adds to it. Both are independent of instructions.agents_md.
kindDisplay nameVersioned slug
pi_corePiagenta:harness:pi_core:v0
claudeClaude Codeagenta:harness:claude:v0
codexCodexagenta:harness:codex:v0

pi_agenta was an experimental Pi variant, removed in August 2026. A stored config that still carries the value runs as pi_core.

harness.permissions​

Applied by harnesses that gate tool use. Claude Code renders it into .claude/settings.json in the session working directory. Pi uses these rules for its built-in tools. Codex renders no per-tool rules of its own; its tool gating comes from runner.permissions and the permission on each tool entry.

FieldTypeRequiredDefaultDescription
default_mode"default" | "acceptEdits" | "plan" | "bypassPermissions" | nullNonullThe harness's own default permission mode.
allowarray of stringNo[]Per-tool rules approved without prompting.
askarray of stringNo[]Per-tool rules that raise a prompt.
denyarray of stringNo[]Per-tool rules always rejected.

runner​

FieldTypeRequiredDefaultDescription
kind"sidecar"No"sidecar"The engine that drives the harness loop. sidecar is the only value.
permissionsobjectNo{"default": "allow_reads"}The runner-enforced tool execution policy.
extrasobjectNo{}Per-runner knobs passed through unchanged.

runner.permissions​

FieldTypeRequiredDefaultDescription
default"allow" | "ask" | "deny" | "allow_reads"No"allow_reads"allow runs every tool without asking. ask requires approval for every tool. deny refuses every tool. allow_reads runs read-hinted tools and asks for everything else.

A value outside that set is rejected. A permission set on a single tool entry overrides this default for that tool.

sandbox​

FieldTypeRequiredDefaultDescription
kind"local" | "daytona"No"local"Where the agent runs.
credentialsarrayNo[]Project secret references bound to environment variables in the sandbox.
permissionsobject or nullNonullThe declared security boundary. Unset means no declared boundary, and the field never reaches the wire.
extrasobjectNo{}Per-sandbox knobs passed through unchanged, for example a Daytona snapshot.

Each credential entry has secret.slug and a binding shaped as {"type": "env", "name": "VARIABLE_NAME"}.

A deployment restricts which sandbox providers it accepts. A request naming a provider the deployment has not enabled is refused before the run starts.

sandbox.permissions​

FieldTypeRequiredDefaultDescription
network.mode"on" | "off" | "allowlist"No"on"Outbound network policy.
network.allowlistarray of stringNo[]CIDR ranges allowed when network.mode is "allowlist".
filesystem"on" | "readonly" | "off" | nullNonullDeclared only. Not enforced.
enforcement"strict" | "best_effort"No"strict"strict fails the run when the boundary cannot be applied.

The default template​

This is the value a new agent starts with. It is also the default on the agent workflow's /inspect parameters schema.

{
"instructions": {
"agents_md": "You are a friendly hello-world agent running on the Agenta agent service.\n\n- Greet the user warmly.\n- Answer the user's message in one or two short sentences."
},
"llm": {
"provider": "openai",
"model": "gpt-5.6-luna"
},
"tools": [],
"mcps": [],
"harness": { "kind": "pi_core" },
"runner": { "kind": "sidecar", "permissions": { "default": "allow_reads" } },
"sandbox": { "kind": "local" }
}

An empty tools array adds no configured tools. The harness built-ins remain active.

Rejected shapes​

The parser returns HTTP 400 instead of falling back to a default when:

SentErrorUse instead
A flat model key on the templatePre-migration flat keyllm.model
A flat agents_md key on the templatePre-migration flat keyinstructions.agents_md
harness or sandbox as a bare stringPre-migration flat selector{"kind": "..."}
A key other than kind, permissions, or extras inside harness, runner, or sandboxUnknown selector keyOne of the three allowed keys
A runner.permissions.default outside the four modesInvalid permission defaultallow, ask, deny, or allow_reads

Embed references​

A tools or skills entry can be an @ag.embed reference instead of an inline object. Agenta resolves it into the inline shape server-side, before the runner sees it.

{
"@ag.embed": {
"@ag.references": { "workflow": { "slug": "pdf-report" } },
"@ag.selector": { "path": "parameters.skill" }
}
}