Agent definition
Define the model, instructions, tools, and policies once, in TypeScript or JSON.
An agent definition is the configuration Cereal uses to run an agent. It describes which model to call, what instructions to follow, which tools are available, and what rules govern execution. You can author it in TypeScript or send JSON over HTTP.
Cereal stores each changed definition as a version. A session pins one version when it starts, so updating the agent affects new sessions. Your application continues to host its custom tool code on your existing server or serverless platform.
One definition, two ways to write it
These examples register the same agent. First register a provider
named primary with your own model key and select a model available to that account.
The example uses Anthropic; a different supported provider changes only model.
import { createCerealClient, defineAgent } from "@trycereal/sdk"
export const research = defineAgent({
agent: {
slug: "research",
name: "Research",
model: { provider: "primary", model: "claude-sonnet-4.6" },
system: "Research the question and cite the evidence. Ask for missing details.",
policies: {},
limits: { maxTurns: 12 }
}
})
// Uses CEREAL_API_KEY with control scope.
const client = createCerealClient({})
await client.agents.upsert({ slug: research.slug, definition: research.definition() })The SDK fills in tools: []. research.definition() returns the JSON document sent
to Cereal. It does not include slug, which identifies the agent in the upsert request.
See SDK setup if you have not installed the repository SDK.
The HTTP definition requires name, model, system, tools, policies, and limits.
Use [] for no tools and {} for default policies and limits. The TypeScript authoring
helper supplies those empty values and defaults name to the slug when omitted.
The parts of an agent
| Field | What it controls | Details |
|---|---|---|
name, description | The agent's display name and optional description. | The slug belongs to the registration request. |
model | A registered provider name, model ID, reasoning level, and optional fallback models. | Providers, reasoning, fallback |
system | Instructions used across the agent's sessions. | Keep customer-specific context in session inputs. |
tools | MCP connections, inline MCP servers, and provider tools. | Connect tools |
policies | Which tool calls run, wait for approval, or are denied; approval expiry. | Approvals |
limits | Model-step and session token limits. maxTurns caps model steps within a turn. | Usage and budgets |
toolLoading | When tool schemas are loaded into context. | Deferred tools |
compaction | When long context is compacted and what recent messages are kept. | Context and caching |
overrides | Which instructions, model settings, and tools a session may change. | Session overrides |
identity | Whether a session must identify the user or system it acts for. | Application identity |
sandbox | A managed workspace, image, resources, lifecycle, and available sandbox tools. | Sandboxes |
subagents, subagentPolicy | Other agents it may delegate to and limits on their work. | Sub-agents |
experiment, evaluators | Variant assignment and evaluation configuration. | Experiments and evaluations |
See the AgentDefinition schema for every nested field and allowed value. Model credentials are stored in providers, separately from the agent. Session messages, metadata, and the current user's identity are inputs to each session, rather than properties to hard-code in the reusable definition.
Connect the definition to your tools
A tool definition tells Cereal how to reach a capability. The tool's implementation
runs in your application or the service you connect. For an existing MCP connection
named sources, add this entry to the definition's tools array:
{ "type": "mcp", "connection": "sources", "allow": ["read_source"] }With TypeScript, defineAgent({ agent: { ... }, tools: [tool({ ... })] }) keeps handlers
beside the agent configuration. Its definition() adds an MCP connection entry for
those handlers. Agent actions initialize the connection and definition on first use;
agent.init() does this early, and sync() explicitly registers configuration. Mount
agent.fetch or agent.handlers in your app. Use configureCereal({ publicUrl }) or
CEREAL_PUBLIC_URL for your app's HTTPS origin.
See write tools in TypeScript for the complete example.
Provider tools run with the model provider. Sandbox tools run in Cereal-managed sandboxes. Adding a sandbox makes its permitted tools available without hosting a machine in your application.
How a session uses the definition
- Your app creates a session and supplies its first message, optional metadata, and authenticated user identity. Cereal pins the agent version and validates overrides.
- Cereal sends the instructions, conversation context, and available tool schemas to the configured model provider.
- When the model requests a tool, Cereal checks the tool policy. It executes an allowed call, waits for a decision, or returns a denial.
- The tool result returns to the model. Cereal records the work and continues until the model finishes, a limit is reached, or the session needs an external action.
- Your app reads the response and status through the API or session stream. A later message starts another turn in the same session.
Cereal keeps this work independent of your app's request lifetime. Your app remains responsible for authenticating users and authorizing access to its data and sessions. See sessions and turns for lifecycle and recovery behavior.
Versions
agents.upsert finds an agent by slug and creates a version only when the definition
changes. agents.update can require an expected version to prevent overwriting a
concurrent edit:
await client.agents.get({ id: agentId })
await client.agents.versions({ id: agentId })
await client.agents.update({ id: agentId, definition, expectedVersion: 7 })A mismatch returns VersionConflict. Existing sessions retain their pinned definition.
Versioning does not freeze the code behind a tool URL; keep that code compatible or
use versioned callback URLs for breaking changes.
An agent with a sandbox must finish its image build before a session can start.
Check agents.imageStatus({ id: agentId }); baking means wait, and failed means
inspect the build error. Starting early returns AgentNotReady.
agents.rebake rebuilds the latest image without creating a definition version.
Reasoning
model.reasoning accepts none, minimal, low, medium, high, or max.
Support depends on the provider and model. If the adapter cannot represent a level,
it omits that option. The effective setting appears in model.request.started.
Fallback
Add a fallback list when another model should handle a failed request:
model: {
provider: "primary",
model: "claude-sonnet-4.6",
fallback: {
models: [{ model: "claude-haiku-4.6" }],
on: ["unavailable", "rate_limited", "timeout", "server_error"]
}
}A fallback inherits the primary provider and reasoning unless it supplies its own. Cereal retries the current model before moving to the next one. Errors outside the configured reasons fail the turn. Each attempt appears separately in the trace.
Deployments
Code-defined agents register in the environment bound to CEREAL_API_KEY when the SDK
initializes. Deploy your application with the appropriate key for each environment.
See deployment. Agents managed in the console can be
copied to another environment.