# Agent patterns

> Choose a proven Agent composition by the shape of the work, then implement it with the seven primitives and governed Resources.

Agent names describe a product; patterns describe its control flow. A legal assistant and a support assistant may share the same dialogue pattern. A research Agent and a coding Agent may both use planner–worker delegation. Choose the smallest structural pattern that matches the work, then add domain prompts, Resources, Memory, Channels, Credentials, and Policy.

## Pattern catalog {#pattern-catalog}

| Family | Pattern | Use it when | Core composition |
| --- | --- | --- | --- |
| Dialogue | Conversational assistant | One bounded answer depends on session history | `ledger → turn → commit` |
| Dialogue | Content or generation Agent | The output is primarily a model-produced artifact | `turn → commit` |
| Dialogue | Router or triage Agent | The Agent classifies and hands work to a bounded destination | `turn → commit` or `turn → spawn` |
| Dialogue | Customer-support Agent | Conversation may read systems, act, or escalate | `ledger → turn → await? → commit` |
| Knowledge | Retrieval or knowledge Agent | Answers must be grounded in governed records | Resource search `→ turn → commit` |
| Knowledge | Research Agent | Several independent questions or sources must be investigated | `turn → spawn* → turn → commit` |
| Knowledge | Document-intelligence Agent | Many documents need extraction, comparison, or synthesis | `map → reduce → turn → commit` |
| Data | Data analyst Agent | A question requires governed queries and interpretation | `turn → Resource → turn → commit` |
| Data | Batch enrichment or transformation Agent | The same bounded operation applies across large volume | `map → reduce? → commit` |
| Data | Evaluator or judge Agent | Outputs need a rubric, score, gate, or comparison | `turn(gate) → commit` |
| Action | ReAct Agent | The model must observe Tool results and continue until it can finish | `react()` from `@constal/std` |
| Action | Tool-using operator | The model chooses among bounded external operations | `turn(Tools) → commit` |
| Action | Workflow automation Agent | Progress crosses steps, retries, or invocations | durable state `→ commit` |
| Action | Human-approval Agent | Authority must pause for a person or external decision | `turn → await → commit` |
| Action | Browser or computer-use Agent | A governed Resource exposes interactive operations | repeated `turn → Tool`, then `commit` |
| Engineering | Coding Agent | Repository inspection, edits, tests, and review form a loop | `turn → Resources → turn → commit` |
| Operations | Monitoring or incident Agent | Events trigger diagnosis, mitigation, and escalation | `ledger → turn → await? → commit` |
| Coordination | Planner–executor Agent | Planning and execution need separate durable work | `turn → spawn* → turn → commit` |
| Coordination | Supervisor or multi-Agent system | Specialized workers can proceed independently | `spawn* → derived join → turn → commit` |
| Autonomy | Long-horizon Agent | Work must resume across time with explicit progress | durable state composed from all seven |

These are structural archetypes, not an industry list. Sales, legal, healthcare, finance, education, and security Agents are domain applications of one or more rows. Combining patterns is normal; inventing a new runtime primitive for each label is not.

## Start with the bounded core {#bounded-core}

```ts
import { agent } from "@constal/sdk";

export default agent({
  id: "bounded-assistant", version: "1.0.0", model: "model",
  async onMessage(input, ctx) {
    const history = await ctx.ledger.view("history");
    const answer = await ctx.turn({
      system: "Complete one bounded objective and state uncertainty.",
      objective: input,
      context: { history },
    });
    await ctx.commit({ kind: "answer", text: answer.message.content });
    return answer.message.content;
  },
});
```

Add `await` only when time or authority crosses the invocation. Add `spawn` when child work needs an independent durable identity. Add `map` and `reduce` when the cardinality is data volume rather than a bounded worker set. External search, databases, browsers, repositories, ticketing systems, and Memory stay Resources; they do not become primitives.

## Build a ReAct Agent with the library {#react-library}

ReAct is a standard-library composition, not another Agent primitive. `react()` from `@constal/std` supplies the durable state machine, transcript handling, Tool loop, steering intake, and explicit `final` Tool. The Agent definition only adds its identity, Model binding, instructions, and offered Tools.

```ts
import { agent } from "@constal/sdk";
import { react, type ReactState } from "@constal/std";

const behavior = react({
  system: "Research the request with the offered Tools. Call final only when the answer is supported.",
  tools: ["search", "read_page"],
  window: 40,
});

export default agent<ReactState>({
  id: "research-assistant",
  version: "1.0.0",
  model: "model",
  ...behavior,
});
```

`search` and `read_page` must be registered Tools exposed by the Agent deployment; `react()` does not create those capabilities or bypass their Resource and Policy boundaries.

Use `window` to bound the messages sent to each Model turn. Windowing does not rewrite the durable transcript. For long-running Agents, provide `fold` to compact older working context into a serializable summary while retaining the recent messages that still matter:

```ts
const behavior = react({
  system: "Investigate the objective and call final with a supported answer.",
  tools: ["search", "read_page"],
  window: 40,
  async fold(recent, summary, ctx) {
    if (recent.length < 32) return { context: recent, summary };

    const compacted = await ctx.turn({
      system: "Preserve decisions, evidence, open questions, and source references. Remove repetition.",
      objective: { previousSummary: summary, messages: recent },
    });

    return {
      context: recent.slice(-12),
      summary: compacted.message.content,
    };
  },
});
```

Compaction changes the context prepared for later turns, not the Run's recorded history. Keep the fold deterministic in structure, treat its summary as model-generated context rather than business truth, and use `commit` for facts that must become authoritative.

## Implementation guides {#implementation-guides}

- [Dialogue and support Agents](/docs/agents/patterns/dialogue-and-support.md)
- [Research and knowledge Agents](/docs/agents/patterns/research-and-knowledge.md)
- [Data and evaluation Agents](/docs/agents/patterns/data-and-evaluation.md)
- [Action and workflow Agents](/docs/agents/patterns/action-and-workflow.md)
- [Software and operations Agents](/docs/agents/patterns/software-and-operations.md)
- [Multi-Agent and long-horizon systems](/docs/agents/patterns/coordination-and-autonomy.md)
