# Quickstart

## Install

```bash
npm install @ai-for-dev/combo       # the library
pi install npm:@ai-for-dev/combo    # the same package, loaded into pi
```

Node 23.6 or later is required: it runs TypeScript natively, and there is no
build step. The package ships the TypeScript it was written in, and `tsc` is
used only to typecheck.

From a clone, the same three commands the CI runs:

```bash
npm install
npm test          # offline, no network calls
npm run typecheck
```

A model is needed for anything that actually talks to a provider. pi resolves it
the usual way, and the examples take `--model` on the command line:

```bash
node examples/01-run.ts --model local/qwen/qwen3-coder-next
```

Not every provider reports tokens. When one does not, the usage lines read `0`,
and that is deliberate: nothing here is estimated by counting characters. See
[Measurements](measurements.md).

## One subagent, one task

The high level form is disposable: it spawns, asks, and closes.

```typescript
import { findAgent, loadAgents, run } from "@ai-for-dev/combo";

const agents = loadAgents();
const scout = findAgent(agents, "scout");

const result = await run(scout, "Find the authentication code");
console.log(result.output);
console.log(result.usage.turns, result.usage.input, result.usage.cost);
```

`run` never throws on a model failure. It returns a `Result` with `ok: false`
and an `error`, and the usage it managed to spend is still filled in.

## A subagent that remembers

The low level form gives you the object, and you decide how long it lives.

```typescript
import { spawn } from "@ai-for-dev/combo";

const coder = await spawn(coderAgent, { lifetime: "workflow" });
try {
	await coder.ask("Implement the parser");
	await coder.ask("Apply these remarks: …");   // it remembers the previous turn
	console.log(coder.usage);                     // cumulative since spawn
} finally {
	await coder.close();
}
```

Whoever opens, closes. The `finally` is not decoration: an undisposed session
leaks, and closing is also what triggers an export when one was asked for.

Read [Lifetime](lifetime.md) before choosing anything other than the default.

## A workflow

Combinators take agents and give back results. They compose because they all
speak the same `Result`.

```typescript
import { chain, fanOut, loop, saysWord } from "@ai-for-dev/combo";

await chain({ steps: [scout, reviewer], input: "Explain how usage is measured" });

await fanOut({ agent: scout, tasks: ["find A", "find B", "find C"], concurrency: 2 });

await loop({
	steps: [coder, reviewer],
	input: "Implement the parser",
	until: (step) => saysWord(step.output, "LGTM"),
	lifetime: "workflow",
});
```

Set a deadline on anything unattended. There is no default one, and pi's agent
loop has no step cap:

```typescript
await fanOut({ agent: scout, tasks, timeoutMs: 60_000 });   // per branch, not total
```

[Workflows](workflows.md) covers every combinator.

## From pi

```bash
pi -e extension          # this session only
pi install ./extension   # permanently, via settings
```

Then, in the TUI:

```
> /run build add a slugify helper with tests
> use subagent with scope "project" and agent "scout" to find the auth code
```

The demo agents of this repository live in `.pi/agents/`, which is
repository-controlled content and therefore never loaded by default - hence the
explicit `scope`. See [Agents](agents.md) and [Extension](extension.md).

## Next

- [Agents](agents.md) - write your own.
- [Workflows](workflows.md) - the shapes available.
- [Deliver a change](build.md) - the whole build, from a request to a finished working tree.
