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

# Agents

> Define ai_human and dual_ai agents, including subagent lifecycle behavior

## What Are Agents?

Agents define conversation orchestration:

* `ai_human`: AI side responds to user messages
* `dual_ai`: side A and side B alternate until stop conditions are met

Agents reference prompts, define stop semantics, and can be exposed as callable tools.

## Basic Example

```typescript theme={null}
import { defineAgent } from '@standardagents/builder';

export default defineAgent({
  name: 'support_agent',
  type: 'ai_human',
  sideA: {
    label: 'Support',
    prompt: 'support_prompt',
    stopOnResponse: true,
  },
});
```

## Side Configuration

`sideA` is required. `sideB` is required for `dual_ai`.

Common side fields:

* `prompt`
* `label`
* `stopOnResponse`
* `stopTool`
* `stopToolResponseProperty`
* `maxSteps`

Session lifecycle fields:

* `sessionStop`
* `sessionFail`
* `sessionStatus`

Lifecycle fields support:

* string form: `'tool_name'`
* object form: `{ name, messageProperty?, attachmentsProperty? }`

Object form is recommended for subagent workflows because it explicitly maps which tool args become parent-visible message text and attachments.

## Exposing Agents as Tools

```typescript theme={null}
defineAgent({
  name: 'billing_specialist',
  type: 'ai_human',
  exposeAsTool: true,
  toolDescription: 'Handle billing and payment escalations.',
  sideA: {
    prompt: 'billing_prompt',
    stopOnResponse: true,
  },
});
```

Behavior depends on agent type:

* callable `ai_human`: handoff-style tool interaction
* callable `dual_ai`: subagent execution in child thread

## dual\_ai as Subagents

When a `dual_ai` agent is called via prompt tools, AgentBuilder can run it as a child thread with:

* isolated message history/logs/filesystem
* parent/child linkage and child registry
* blocking/non-blocking behavior
* resumable/non-resumable lifecycle

For resumable subagents, runtime lifecycle tools (`subagent_create`, `subagent_message`) are injected by the runtime, not user-defined in `agents/tools`.

`subagent_create.arguments` is validated from the receiving child side's prompt schema and persists with the child thread as `ThreadState.arguments`. Both child sides can read it and use its top-level keys as prompt variables.

## Example: Worker + Reviewer

```typescript theme={null}
defineAgent({
  name: 'asset_subagent',
  type: 'dual_ai',
  maxSessionTurns: 40,
  exposeAsTool: true,
  toolDescription: 'Generate and QA top-down assets.',
  sideA: {
    label: 'Worker',
    prompt: 'asset_worker',
    stopOnResponse: true,
    sessionFail: {
      name: 'fail_asset',
      messageProperty: 'summary',
      attachmentsProperty: 'attachments',
    },
  },
  sideB: {
    label: 'Reviewer',
    prompt: 'asset_reviewer',
    stopOnResponse: false,
    sessionStop: {
      name: 'approve_asset',
      messageProperty: 'summary',
      attachmentsProperty: 'attachments',
    },
    sessionStatus: {
      name: 'asset_status',
      messageProperty: 'status',
    },
  },
});
```

## Best Practices

* Always set `maxSessionTurns` for `dual_ai`
* Use `sessionStop` / `sessionFail` for explicit terminal outcomes
* Use object-form lifecycle bindings when payload shape matters
* Keep side prompts specialized (`side_a` production, `side_b` QA)

## Related Docs

* [Subagents](/core-concepts/subagents)
* [Prompts](/core-concepts/prompts)
* [defineAgent](/api-reference/define/agent)
