ASK KNOX
beta
LESSON 305

Defining Your Agent

An agent definition is the contract between your requirements and Anthropic's infrastructure — every field is a decision with operational consequences.

9 min read·Claude Managed Agents

An agent in the Managed Agents API is a durable resource — not a temporary configuration you pass per-call, but a named, versioned definition that persists and is referenced by sessions. This distinction matters. You create an agent once and run it many times. The agent definition is the contract.

Getting the definition right is the architectural work. The API call to create it is trivial. Understanding what each field does and why — and what the consequences of getting it wrong are — is the lesson.

The Core Fields

import anthropic

client = anthropic.Anthropic()

agent = client.beta.agents.create(
    name="competitor-intelligence-agent",
    model="claude-sonnet-4-6",
    system="""You are a competitive intelligence specialist. 
When given a company name, gather publicly available information 
about their recent product launches (last 90 days), funding rounds, 
executive changes, and strategic announcements.

Synthesize findings into a structured report with these sections:
- Recent Products
- Business Development  
- Leadership Changes
- Strategic Implications

Cite sources for every claim. Do not speculate beyond what sources support.""",
    tools=[
        {
            "type": "agent_toolset_20260401",
            "default_config": {"enabled": False},
            "configs": {
                "web_search": {"enabled": True},
                "bash": {"enabled": True}
            }
        }
    ],
    skills=[]
)

print(f"Agent created: {agent.id}")

Each field is a decision.

The name Field

The name is not just a label. In multi-agent systems, it is an identifier in session thread events. When an orchestrator agent dispatches work to a subagent, the events that flow back are tagged with the subagent's name. If you name your agent agent-v1, your logs contain agent-v1. If you name it competitor-intelligence-agent, your logs tell you what ran.

Name agents for what they do, not what they are. research-agent is ambiguous. competitor-intelligence-agent is not. In a fleet of ten agents, you will be glad you were specific.

The model Field

The model field pins the agent to a specific Claude model. Use the published model aliases — do not hand-construct date-suffixed model IDs.

For production agents: claude-sonnet-4-6 is the standard starting point. It handles complex reasoning and agentic behavior reliably. claude-opus-4-8 is appropriate for agents that require maximum reasoning depth on frontier tasks. Cost scales significantly — reserve Opus for tasks that justify it.

The model field is part of the agent's version identity. Changing the model is a potentially breaking change — the agent may behave differently, produce different output formats, or make different tool calling decisions. Treat a model change the same way you would treat a major version bump.

The system Field

The system prompt is the agent's constitution. It defines:

  • What the agent does and what it does not do
  • How it should reason through tasks
  • What output format it should produce
  • What quality standards it should apply
  • What it should do when it encounters errors or ambiguity

For Managed Agents, the system prompt carries more weight than in interactive use. There is no human in the loop to redirect the agent when it takes a wrong turn. The system prompt must be thorough enough to handle edge cases without intervention.

Practical rules:

  • Specify output format explicitly. Agents that produce structured output (JSON, markdown with specific sections) should have the format defined in the system prompt, not left implicit.
  • Define error handling. What should the agent do if a web search returns no results? If a tool call fails? If the input is malformed? Specify it.
  • Scope the task. A system prompt that says "you can help with anything" produces agents that drift. Scope the system prompt to the specific task domain.

The tools Field

Tools are the agent's capabilities beyond text generation. The tools array accepts three kinds of entries:

  • {"type": "agent_toolset_20260401"} — the built-in toolset: bash, read, write, edit, glob, grep, web_fetch, and web_search. You enable or disable individual tools with default_config (the baseline for every tool) and configs (per-tool overrides). File search is handled by the glob and grep tools — there is no separate file-search tool.
  • {"type": "mcp_toolset"} — tools exposed by an attached MCP server, enabled the same way with default_config and configs.
  • {"type": "custom"} — your own tools, defined with a name, description, and JSON Schema input (covered in the custom tools lesson).

The critical mistake is enabling every tool by default. Each tool you enable:

  • Increases the token overhead in every turn (the tool schema goes into context)
  • Expands the agent's potential action space, increasing the risk of unintended actions
  • Adds noise to the model's tool-selection reasoning

Enable only tools the agent actually needs for its defined task. A research agent that only reads the web needs web_search. It does not need bash unless it needs to run scripts. A data processing agent needs bash. It may not need web_search.

The skills Field

Skills are versioned knowledge libraries referenced by ID and version. They load into context progressively — full content only when the agent determines the skill is relevant.

# Reference skills in the agent definition.
# Each entry pins a skill ID and version — either an
# Anthropic-provided skill or one you uploaded.
agent = client.beta.agents.create(
    name="competitor-intelligence-agent",
    model="claude-sonnet-4-6",
    system="You are a competitive intelligence specialist...",
    tools=[
        {
            "type": "agent_toolset_20260401",
            "default_config": {"enabled": False},
            "configs": {"web_search": {"enabled": True}}
        }
    ],
    skills=[
        {"type": "custom", "skill_id": "skill_01abc...", "version": 1}
    ]
)

Skills are most useful when the agent has a procedural workflow that is too long to include in the system prompt efficiently, or when the same workflow needs to be reused across multiple agents.

The multiagent Field

In multi-agent architectures, an orchestrator agent can dispatch work to subagents. The top-level multiagent field declares the roster. Set type to "coordinator" and list up to 20 agents — each entry is an agent ID string, a version-pinned reference ({"type": "agent", "id": ..., "version": ...}), or {"type": "self"} to let the agent spawn copies of itself:

orchestrator = client.beta.agents.create(
    name="pipeline-orchestrator",
    model="claude-sonnet-4-6",
    system="You are a research pipeline orchestrator. Decompose research requests into subtasks and dispatch them to specialized agents.",
    multiagent={
        "type": "coordinator",
        "agents": [
            competitor_intel_agent.id,
            {"type": "agent", "id": market_research_agent.id, "version": 2},
            financial_data_agent.id
        ]
    }
)

When the orchestrator calls a subagent, that call creates a new session thread within the parent session. The orchestrator sends a task; the subagent executes it; the result returns to the orchestrator's thread. This enables specialization — each subagent is optimized for its specific task — and parallelism — the orchestrator can dispatch multiple subagents concurrently. Delegation is one level deep: a coordinator dispatches to workers, and the platform ignores any deeper delegation.

Agent Versioning

Versioning is native to the API. Every update to an agent (POST /v1/agents/{id}) creates a new immutable version of that agent. Sessions can pin a specific version with {"type": "agent", "id": ..., "version": ...} — existing callers keep getting the version they pinned until you migrate them.

The discipline this enables:

Routine changes — update, don't re-create. Improving the system prompt, adding tools or skills, even changing the output format: make the change with an update. The new version is created automatically; old versions remain immutable and pinnable. Re-creating a new agent for every change accumulates orphaned agents and defeats the versioning model.

Rollback by pinning. If a new version misbehaves in production, point sessions back at the prior version. The old definition is still there, byte-for-byte.

Reserve new agents for genuinely different personas. A competitor-intelligence agent and a customer-support agent are different agents. A competitor-intelligence agent with a sharper system prompt is a new version of the same agent.

# Publish a new version — the update creates it automatically
client.beta.agents.update(
    agent_id=agent.id,
    system="[updated system prompt with new output format]"
)

# Pin a session to a known-good version for rollback
session = client.beta.sessions.create(
    agent={"type": "agent", "id": agent.id, "version": 3},
    environment_id=environment.id
)

There is no delete endpoint for agents — only archive. Archive agents you no longer use; archived definitions remain available for audit.