Agent, Workflow, and Harness Reference
Purpose and Scope
This reference orients developers who are deciding between the AI SDK agent loop, durable workflow agents, and harness-backed coding agents. In this documentation set, an agent is a runtime that can call a model, use tools, and continue across one or more turns. A workflow agent adds durable execution semantics for production systems that need checkpoints, retries, and human approval boundaries. A harness adapter connects that agent-shaped API to an external coding-agent runtime while still presenting AI SDK-compatible generate() and stream() methods to application code.
Harnesses are useful when the model interaction is not just a single provider request. A coding harness may need a filesystem, a shell, built-in editing tools, and runtime-specific authentication. The Pi harness page shows this shape clearly: the adapter connects HarnessAgent to @earendil-works/pi-coding-agent, runs Pi in the host Node.js process, and uses the sandbox as a remote filesystem and shell instead of installing a bridge inside the sandbox. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
Relevant Source Files
content/providers/02-ai-sdk-harnesses/03-pi.mdx— Defines the reader-facing Pi harness adapter page, including setup commands, imports,HarnessAgentusage, adapter settings, authentication, sandbox requirements, built-in tools, approval behavior, and related harness documentation links.
System-to-Code Mapping
The public mental model has three layers. HarnessAgent is the application-facing agent class; the harness adapter is the runtime-specific connector; and the sandbox provider supplies an isolated workspace for filesystem and shell operations. In the Pi example, application code imports HarnessAgent from @ai-sdk/harness/agent, imports pi or createPi from @ai-sdk/harness-pi, and creates a sandbox with createVercelSandbox from @ai-sdk/sandbox-vercel. The resulting agent can create a session and stream a prompt through the configured harness. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
This layering matters because the adapter is not the same thing as a model provider. A model provider normalizes language-model calls, while a harness adapter normalizes a full coding-agent runtime: sessions, streams, built-in tools, authentication, and sandbox interaction. The supplied Pi source also marks harness packages as experimental, so callers should treat these APIs as early interfaces whose exact options and runtime capabilities may change between releases. That experimental status is especially important for long-lived automation and platform integrations that would otherwise assume stable adapter behavior. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
HarnessAgent and Session Flow
A harness-backed agent starts with construction, then session creation, then one or more prompt turns, and finally cleanup. The Pi usage example constructs new HarnessAgent({ harness: pi, sandbox: createVercelSandbox({ runtime: 'node24' }) }), then calls agent.createSession(). The prompt turn uses agent.stream({ session, prompt }), and the result exposes an async stream whose parts can be inspected. The example writes text-delta parts to standard output and calls session.destroy() in a finally block so the sandbox-backed session is cleaned up even when the turn fails. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
import { HarnessAgent } from '@ai-sdk/harness/agent';
import { pi } from '@ai-sdk/harness-pi';
import { createVercelSandbox } from '@ai-sdk/sandbox-vercel';
const agent = new HarnessAgent({
harness: pi,
sandbox: createVercelSandbox({
runtime: 'node24',
}),
});
const session = await agent.createSession();
const result = await agent.stream({
session,
prompt: 'Check the test failures and fix the production code.',
});
for await (const part of result.stream) {
if (part.type === 'text-delta') {
process.stdout.write(part.text);
}
}
await session.destroy();Use generate() when a caller wants an AI SDK-compatible final result, and use stream() when the UI, terminal, or orchestration layer should react to incremental output. The Pi source demonstrates the streaming shape rather than a terminal UI package directly, but the same event-driven pattern is what terminal experiences need: create a session, send a prompt, consume deltas, surface tool progress when available, and guarantee cleanup. For durable workflow agents, the official docs position WorkflowAgent as the choice when the loop must survive workflow step boundaries, retries, and approval pauses.
Pi Harness Adapter API
The Pi adapter has two public imports: pi and createPi. The default pi export is equivalent to calling createPi() with default configuration, which is the simplest choice for a first integration. Use createPi() when the runtime needs explicit model selection, auth, or reasoning budget configuration. The documented settings are auth, model, and thinkingLevel: auth supplies AI Gateway or custom provider environment configuration, model selects a Pi model id or name, and thinkingLevel configures the Pi thinking budget level. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
import { pi, createPi } from '@ai-sdk/harness-pi';
const harness = createPi({
model: 'anthropic/claude-sonnet-4.6',
thinkingLevel: 'medium',
});Authentication is resolved through either explicit adapter configuration or host environment variables. When no explicit auth is configured, the Pi page says the adapter checks for AI_GATEWAY_API_KEY or VERCEL_OIDC_TOKEN. For custom providers, pass auth.customEnv with conventional key pairs such as OPENAI_API_KEY, OPENAI_BASE_URL, ANTHROPIC_API_KEY, or ANTHROPIC_BASE_URL. This keeps provider credentials outside the prompt loop while still letting the harness runtime access the model provider it needs. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
const harness = createPi({
auth: {
gateway: {
apiKey: process.env.AI_GATEWAY_API_KEY,
},
},
});Sandbox, Built-in Tools, and Approvals
Every Pi-backed HarnessAgent needs a HarnessV1SandboxProvider, but Pi has a different sandbox constraint than bridge-backed harnesses. The Pi source states that it does not require exposed ports because the runtime runs in the host Node.js process and uses the sandbox as a remote filesystem and shell. That means a network sandbox such as @ai-sdk/sandbox-vercel works, and a local emulation such as @ai-sdk/sandbox-just-bash can also be appropriate when the application does not need a sandbox-exposed network port. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
The adapter exposes common Pi built-ins through agent.tools: read, write, edit, bash, grep, glob, and ls. These tools are important because harness agents often operate on codebases rather than plain chat transcripts. A UI or terminal integration can inspect the agent’s available tools to decide what to display, what to request approval for, and how to explain runtime actions to a user. The Pi page also notes that additional built-ins may appear when they do not fit one of the common tool shapes. Sources: content/providers/02-ai-sdk-harnesses/03-pi.mdx
Approvals are part of the harness contract when a runtime can ask before executing sensitive operations. The Pi source states that built-in tool approval requests are supported when permissionMode is allow-reads or allow-edits. In practice, callers should treat approvals as an execution boundary, not as a cosmetic UI event: the agent may need to pause, present the requested action, receive a decision, and continue only when the decision allows it. Workflow-style agents extend this idea by making approval pauses durable across workflow boundaries.
Compact API Reference
| Component | Public names or fields | Behavior |
|---|---|---|
| Harness agent | HarnessAgent | Application-facing agent class used with a harness adapter and sandbox provider. |
| Pi adapter imports | pi, createPi | pi is the default configuration; createPi() returns a configured Pi harness. |
| Pi settings | auth, model, thinkingLevel | Configure credentials, model id or name, and Pi thinking budget. |
| Session flow | agent.createSession(), agent.stream({ session, prompt }), session.destroy() | Create an isolated run context, send a streaming prompt turn, and clean up resources. |
| Sandbox provider | HarnessV1SandboxProvider, createVercelSandbox({ runtime: 'node24' }) | Supplies the remote filesystem and shell used by Pi. |
| Built-in tools | read, write, edit, bash, grep, glob, ls | Exposed through agent.tools for coding-agent operations. |
| Approval mode | permissionMode values such as allow-reads or allow-edits | Enables built-in tool approval requests for Pi. |
Execution Guidance and Next Steps
Start with a harness when the task requires a coding-agent runtime rather than a single model call. Choose Pi when running the agent in the host process with sandbox-backed filesystem and shell access matches your deployment model. Keep the construction boundary explicit: adapter configuration belongs in createPi(), workspace isolation belongs in the sandbox provider, and prompt turns belong on HarnessAgent. This separation makes it easier to swap adapters later and to move from an experimental prototype toward a durable workflow or terminal-oriented experience.
For production agents, evaluate whether the loop needs workflow durability before committing to an in-memory session lifecycle. If the agent must survive retries, wait for human approval, or expose progress as workflow steps, continue to the WorkflowAgent documentation. If the priority is local or terminal operation, build around the same streaming result shape shown here and add presentation logic around text deltas, tool events, approval prompts, and cleanup. Related pages: building-agents, workflow-agent-and-terminal-ui, tool-approvals, configuration-options-tools-that-use-experimental-sandboxes-experimental-sandbox-section-in-tool-calling.