<!-- Generated by scripts/gen-docs.ts from the TSDoc in src/. Do not edit by hand. -->

# `agent`

Source: [`src/agent.ts`](https://github.com/AI-for-dev/combo/blob/main/src/agent.ts)

An agent is *content*: a system prompt, a model, a set of tools.
It is declared as Markdown + frontmatter, following the pi convention.

This file knows nothing about sessions or workflows: it turns files into
data. Bringing an agent to life is `spawn()`'s job.

## `Agent`

*type*

```typescript
export type Agent = {
	/** Unique name, and how every caller refers to it. Mandatory in the file. */
	name: string;
	/**
	 * What this agent is for, in one line. Mandatory in the file.
	 *
	 * Not decoration: `route` and `orchestrate` hand this text to a model to
	 * decide who does the work, so a vague description produces vague routing
	 * that no parser can repair.
	 */
	description: string;
	/** Markdown body, used verbatim as the system prompt. */
	systemPrompt: string;
	/**
	 * Allowed tools. Absent means the read-only default is applied at spawn;
	 * an empty list means none at all.
	 */
	tools?: string[];
	/**
	 * Every turn must call at least one tool. A turn that answers without one
	 * fails with {@link CALLED_NO_TOOL_ERROR}: for an agent whose job is to
	 * read, an answer that read nothing is one that was not done.
	 */
	mustCallTool?: boolean;
	/**
	 * Skills this agent may load, by name - an allowlist, exactly like `tools`.
	 *
	 * Absent means none: a subagent is offered no skill it did not ask for.
	 * `resolveSkills` in `src/skills.ts` says where a name is looked up.
	 */
	skills?: string[];
	/** Model pattern, e.g. `"anthropic/claude-sonnet-5"`. Absent means pi's default. */
	model?: string;
	/** Default lifetime, in a workflow as in `spawn`. An explicit call always wins. */
	lifetime?: Lifetime;
	/**
	 * How many subagents this agent runs at once when it delegates.
	 *
	 * Only meaningful for an agent whose `tools:` names `subagent`. It is the
	 * agent's own business rather than the caller's: how wide a split is worth
	 * making depends on how the agent was told to think about its task, which is
	 * what its definition says.
	 */
	concurrency?: number;
	/**
	 * Default for "give this agent its own herdr split". An explicit call wins.
	 *
	 * Declaring it here is often what you want: a scout is worth watching every
	 * time, whoever calls it.
	 */
	openInHerdr?: boolean;
	/** Where the definition was found - a repository's agents are loaded only on request. */
	source: AgentSource;
	/** File path, or a free label for an agent built in memory. */
	filePath: string;
};
```

An agent: the "who". Inert data, no state, no session.

## `AgentScope`

*type*

```typescript
export type AgentScope = "user" | "project" | "both";
```

Where to look for definitions. Defaults to `"user"` - see {@link loadAgents}.

## `AgentSource`

*type*

```typescript
export type AgentSource = "user" | "project" | "builtin";
```

Where an agent definition came from.

`"builtin"` is what this package ships. It is the lowest priority of the
three: a `"user"` definition of the same name replaces it, and a `"project"`
one replaces both.

## `findAgent`

*function*

```typescript
export function findAgent(agents: Agent[], name: string): Agent { /* … */ }
```

Looks up an agent by name, or throws.

An unknown agent name is a programming error, not a runtime failure: we do
not want a failed `Result` several steps later because of a typo in a
workflow.

## `Lifetime`

*type*

```typescript
export type Lifetime = "task" | "workflow" | "session";
```

Lifetime of a subagent - the central choice of this library.

- `"task"`: born and dies with each task. Minimal context, reproducible.
- `"workflow"`: lives for the duration of the workflow. Remembers iterations.
- `"session"`: lives as long as the pi session. Long memory, watch it.

## `LIFETIMES`

*const*

```typescript
export const LIFETIMES = ["task", "workflow", "session"] as const satisfies readonly Lifetime[];
```

Every {@link Lifetime}, for whoever validates one - the tool's schema names them from here.

## `loadAgents`

*function*

```typescript
export function loadAgents(options: { cwd?: string; scope?: AgentScope; builtin?: boolean } = {}): Agent[] { /* … */ }
```

Discovers the available agents.

The scope defaults to `"user"`, and that is not a detail: project agents
(`.pi/agents/`) are repository-controlled content, hence third-party
instructions. They are only loaded on explicit request.

Precedence runs from the least specific to the most: the shipped definitions
first when `builtin` is set, then the user's, then the repository's. Whoever
is closer to the work wins the name. `builtin` is off by default: a script
that asks for "the user's agents" must not be handed ours as well. The
extension asks for them, because there it is the difference between working
out of the box and not working at all.

Discovery happens on every call: editing a `.md` is enough to reload it.

## `loadAgentsFromDir`

*function*

```typescript
export function loadAgentsFromDir(dir: string, source: AgentSource): Agent[] { /* … */ }
```

Reads every `.md` in a directory.

A file that does not parse is **dropped in silence** - that is pi's own
behaviour for an agent, and we keep it. A missing or unreadable directory
yields `[]`.

## `parseAgent`

*function*

```typescript
export function parseAgent(content: string, filePath: string, source: AgentSource): Agent | undefined { /* … */ }
```

Parses an agent definition.

Returns `undefined` when the frontmatter is not valid YAML, or when `name` or
`description` is missing: this is pi's behaviour, a file that is not an agent
is ignored **silently**. Kept separate from {@link loadAgents} so it stays
testable without touching the disk.
