> ## Documentation Index
> Fetch the complete documentation index at: https://docs.duraton.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent kit

> Write an AI agent as a durable workflow: agent() and tool() from @duraton/agent-kit, where every model turn and tool call is a step that survives a crash.

This page is for the code path - building or extending an agent by hand. To build one without
code, start with [Build your first agent](/start/first-agent).

`@duraton/agent-kit` is the authoring layer on top of [`step.ai.loop`](/reference/sdk/ai-steps#step-ai-loop).
You declare a model, some instructions and some tools; the kit composes the model call for each
turn. Everything durable stays where it already was - one step per turn, one per tool call,
reused on replay - so an agent written with the kit is an ordinary durable run.

```sh theme={null}
npm install @duraton/agent-kit
```

## A first agent

```ts theme={null}
import { agent, tool } from "@duraton/agent-kit";
import { workflow } from "@duraton/sdk";

const searchPolicy = tool({
  name: "search-policy",
  description: "Look up the refund policy that applies to a ticket",
  inputSchema: {
    type: "object",
    properties: { topic: { type: "string" } },
    required: ["topic"],
  },
  handler: (input) => policyIndex.find(parseTopic(input)),
});

export const support = workflow<{ ticket: string }>({
  name: "support.agent",
  handler: async (ctx) => {
    const result = await agent(ctx, "agent", {
      model: "claude-opus-4-8",
      instructions: "You are a support agent. Check the refund policy before answering.",
      prompt: `Resolve this ticket: ${ctx.event.data.ticket}`,
      tools: [searchPolicy],
      maxIterations: 6,
    });
    return { answer: result.final, iterations: result.iterations };
  },
});
```

That run records `agent:iter:0`, `agent:iter:0:tool:<callId>`, `agent:iter:1`, and so on - the same
step names a hand-written loop writes, which is why an agent needs no special handling to show up
in the console as an agent.

## What is in the kit

<CardGroup cols={2}>
  <Card title="Agents and tools" href="/agent-kit/agents-and-tools">
    `agent()` and `tool()`: model, instructions, tools, behaviour hints, and what the model sees.
  </Card>

  <Card title="Approvals in the loop" href="/agent-kit/approvals">
    Gate a tool call on a person, cap the decisions an agent may ask for, check its arguments.
  </Card>

  <Card title="Structured output" href="/agent-kit/structured-output">
    Answer in a declared shape, validated and recorded as a durable step.
  </Card>

  <Card title="Providers and MCP" href="/agent-kit/providers-and-mcp">
    Bring your own provider, attach an external MCP server, expose your tools over MCP.
  </Card>
</CardGroup>

## The kit adds no loop

`agent()` holds no iteration counter, no history and no retry logic. `step.ai.loop` already owns
all three, and its `turn` is the extension point the kit fills. That is what keeps an agent
resumable after a crash, free of repeated model calls on replay, and visible in the console with
nothing extra to configure.
