# OrchaJS
> OrchaJS is an open-source, filesystem-first JavaScript and TypeScript framework for building durable AI agents inside existing applications.
Website: https://orcha.sh
Source: https://github.com/amarsia/orcha
npm: https://www.npmjs.com/package/orchajs
License: MIT
An agent is a folder. Orcha treats that folder as the complete, portable source of truth. Files define the model, instructions, actions, skills, tests, and evaluations. There is no proprietary orchestration graph, no hosted control plane, and no export step.
It is a library, not a platform. It runs anywhere JavaScript runs: Node.js, React, React Native, Next.js, Express, NestJS, and other JavaScript or TypeScript applications. Add it the way you would add Prisma or Zod.
## Who it is for
- Node.js, React, and other JavaScript or TypeScript teams who want AI agents inside the applications they already ship.
- Product and platform engineers who need pause, resume, human-in-the-loop, tests, and evaluations without a separate agent runtime.
- Teams who want agent behavior versioned in git as ordinary files, not locked inside someone else's dashboard.
## What it is
OrchaJS compiles filesystem-based agent definitions into a typed runtime. After `orcha.init()`, registered agents are called as `orcha.supportBot.run(...)`. Durable sessions persist automatically. The same source runs locally and in production.
The npm package is `orchajs`. Import the runtime singleton as `{ orcha }`. Do not invent path-based runtime APIs.
## What it supports
- Durable sessions: `.run()`, `.resume()`, `.get()`, `.history()`, `.list()`, `.update()`, `.pause()`, and `.events()`.
- Local actions: any trusted Node.js code — APIs, databases, SDKs, third-party services.
- Client actions: pause for the calling app, UI, or a human, then resume with tool results.
- Skills: specialized procedures loaded only when relevant.
- Subagents: parent agents that delegate to private specialists with their own sessions.
- Tests: real-model contract tests with optional mocked actions.
- Evaluations: asynchronous model judges with metrics and thresholds.
- Multimodal input: local files and remote media.
- Sandboxed or native local action execution.
- Production builds through the application's existing `npm run build`.
## Model providers
OpenAI, Anthropic, DeepSeek, Google Gemini (`googlegenai`), Google Vertex AI, and Amazon Bedrock.
## Quickstart
Add Orcha to an existing project:
```sh
npm install orchajs
npx orcha init
```
Or create a new project:
```sh
npx create-orcha@latest my-app-name
```
Give a coding agent the Orcha development guide:
```sh
npx skills add Amarsia/orcha
```
```ts
import "./orcha/index.js";
import { orcha } from "orchajs";
const result = await orcha.exampleAgent.run(
"Help me with my order.",
).result;
```
## Agent structure
```text
orcha/
index.ts
supportBot/
index.json
instructions.md
actions/
skills/
tests/
evaluations/
```
- `orcha/index.ts` initializes providers and registers agents.
- An agent's `index.json` selects provider, model, limits, and text or JSON output.
- `instructions.md` contains the agent's stable role and operating boundaries.
- Actions are typed local or client-owned tools defined with JSON Schema.
- Skills are lazy-loaded procedural instructions.
- Tests run real agent scenarios with optional mocked actions.
- Evaluations are asynchronous LLM judges with explicit metrics and thresholds.
- Durable sessions can be resumed by session ID and can pause for client actions or humans.
# Documentation
# Getting Started
Install OrchaJS in an existing Node.js app or create a new project with create-orcha.
Source: https://orcha.sh/docs
Markdown: https://orcha.sh/docs.mdx
## Prerequisites
Requires Node.js 20.12 or newer and an API key for the model provider of your choice.
## Add Orcha to an existing project
```bash
npm install orchajs
npx orcha init
```
Running `orcha init` in the current directory:
- Creates `orcha/exampleAgent/index.json`
- Creates `orcha/exampleAgent/instructions.md`
- Creates `orcha/index.ts` with Anthropic configured and `exampleAgent` registered
- Creates root-level `AGENTS.md` with the complete Orcha development guide
- Adds `.orcha/` to `.gitignore`
Existing files are skipped, not overwritten.
## Add Orcha as a skill
Give your coding agent the complete Orcha development guide:
```bash
npx skills add Amarsia/orcha
```
## Create a new Node.js project
```bash
npx create-orcha@latest my-app-name
cd my-app-name
npm install
cp .env.example .env
```
The starter includes example agents and scripts for the local development playground, tests, and production compilation.
## Add your provider credentials
Create a root-level `.env` file and add the credentials for the provider configured in `orcha/index.ts`.
### Anthropic
```bash
ANTHROPIC_API_KEY=your-anthropic-key
```
### OpenAI
```bash
OPENAI_API_KEY=your-openai-key
```
### DeepSeek
```bash
DEEPSEEK_API_KEY=your-deepseek-key
```
### Google Gemini
```bash
GOOGLE_API_KEY=your-google-ai-key
```
The provider name in agent configuration is `googlegenai`.
### Google Vertex AI
```bash
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=us-central1
GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/service-account.json
```
Vertex AI can also use Application Default Credentials without
`GOOGLE_APPLICATION_CREDENTIALS`.
### Amazon Bedrock
```bash
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_SESSION_TOKEN=your-session-token
```
Bedrock uses the normal AWS credential chain when explicit credentials are
omitted.
[Read more about model providers →](/docs/model-providers)
---
# Create your first agent
Create your first OrchaJS agent, call .run(), and read the result, stream, and session ID.
Source: https://orcha.sh/docs/first-agent
Markdown: https://orcha.sh/docs/first-agent.mdx
An agent is a folder with model configuration and instructions.
```text
orcha/
index.ts
exampleAgent/
index.json
instructions.md
```
If you ran `npx orcha init`, these files already exist.
## Configure the agent
`orcha/exampleAgent/index.json`:
```json
{
"name": "Example Agent",
"description": "Answer general questions clearly and concisely.",
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"region": "provider_managed",
"maxTokens": 10240,
"outputType": "text"
}
```
## Write its instructions
`orcha/exampleAgent/instructions.md`:
```md
You are a concise and helpful assistant.
Answer the user's question directly before adding supporting detail.
Use clear language and practical examples.
Ask one focused question when the request is ambiguous.
Separate established facts from assumptions.
If you are uncertain, say so instead of inventing an answer.
```
## Register it
`orcha/index.ts`:
```ts
orcha.init({
providers: {
anthropic: process.env.ANTHROPIC_API_KEY ?? "",
},
agents: {
exampleAgent: "./exampleAgent",
},
});
```
The registration key becomes the runtime property
`orcha.exampleAgent`.
## Run it from code
```ts
const agent = orcha.exampleAgent;
const execution = agent.run("What is an idempotent API?");
const result = await execution.result;
if (result.status === "completed") {
console.log(result.output);
}
```
Every call to `run()` creates a new durable session.
## Input reference
`run()` accepts a string or an input object.
### Text
```ts
agent.run("Explain durable sessions.");
```
The equivalent text block is:
```ts
agent.run({
content: {
type: "text",
text: "Explain durable sessions.",
},
});
```
### Local file
```ts
agent.run({
content: [
{ type: "text", text: "Summarize this document." },
{ filePath: "./documents/report.pdf" },
],
});
```
`type: "file"` is optional when `filePath` is present. Relative paths resolve
from the Orcha project root. `mimeType` is inferred from the file extension
when possible, or can be provided:
```ts
{
type: "file",
filePath: "./documents/report.bin",
mimeType: "application/pdf",
}
```
### Remote URL
```ts
agent.run({
content: [
{ type: "text", text: "Describe this image." },
{
url: "https://cdn.example.com/photo.jpg",
mimeType: "image/jpeg",
},
],
});
```
`type: "url"` is optional when `url` is present.
Use `url` for any remote image, document, audio, or video. `mimeType` tells
Orcha what the resource contains. Actual media support depends on the selected
provider and model.
### Additional input fields
```ts
agent.run({
content: "Help with account acct_123.",
name: "Account support",
metadata: {
accountId: "acct_123",
},
variables: {
companyName: "Acme",
},
clientCapabilities: [
"request_human_approval",
],
});
```
- `name` is an optional session label.
- `metadata` stores durable application context.
- `variables` replace `{{ variableName }}` placeholders in instructions.
- `clientCapabilities` lists client actions available to this caller.
## What `run()` returns
`run()` returns an execution handle immediately:
```ts
const {
sessionId,
stream,
result,
snapshot,
evaluations,
} = agent.run("Hello");
```
- `sessionId` is available immediately.
- `stream` is a `ReadableStream` of cumulative execution snapshots.
- `result` is a promise for the final run result.
- `snapshot` is the latest snapshot, or `undefined` before the first update.
- `evaluations` is a promise for asynchronous evaluation results.
Await `result` first. On the resolved run result, `result.output` is the
agent's final output, as shown below.
### Text output
For an agent configured with `"outputType": "text"`, `result.output` is a
string:
```ts
const result = await execution.result;
if (result.status === "completed") {
console.log(result.output); // string
}
```
### JSON output
For an agent configured with `"outputType": "json"`, `result.output` is the
object defined by the agent's `outputSchema`:
```ts
const result = await execution.result;
if (result.status === "completed") {
console.log(result.output); // validated JSON object
}
```
Text and JSON use the same `result.output` property. The difference comes from
the agent configuration, not from a different execution field.
### Result states
```ts
const result = await execution.result;
```
`result.status` is one of:
- `completed` — contains `output` and optional usage.
- `waiting_for_client_action` — contains `clientToolCalls`.
- `paused` — the execution stopped and can be resumed.
- `failed` — contains a structured `error`.
Every result includes `sessionId`. Save it when the conversation may continue
later with `agent.resume(sessionId, ...)`.
[Read the complete multimodal reference →](/docs/multimodal)
---
# Dev playground
Open the OrchaJS local playground with npx orcha playground to run and inspect agents.
Source: https://orcha.sh/docs/dev-playground
Markdown: https://orcha.sh/docs/dev-playground.mdx
From your application directory, run:
```bash
npx orcha playground
```
Orcha opens the local development playground in your browser.
---
# Folder Structure
The OrchaJS folder layout for agents, actions, skills, tests, and the registry.
Source: https://orcha.sh/docs/folder-structure
Markdown: https://orcha.sh/docs/folder-structure.mdx
The `orcha/` directory is the source of truth. Placement determines behavior, so an agent remains understandable by opening its folder.
```text
orcha/
index.ts
supportAgent/
index.json
instructions.md
actions/
lookupOrder/
index.json
index.js
skills/
delayedOrderHandling/
index.json
instructions.md
tests/
delayedOrder/
index.json
evaluations/
supportQuality/
index.json
```
## `orcha/index.ts`
Initializes providers and explicitly registers agents:
```ts
orcha.init({
providers: {
openai: process.env.OPENAI_API_KEY ?? "",
},
agents: {
supportAgent: "./supportAgent",
},
});
```
Only registered agents are compiled. The registration key becomes the runtime property: `orcha.supportAgent`.
## Agent files
### `agent/index.json`
Chooses the provider, model, output type, and model limits. `name`, `provider`, and `model` are required.
```json
{
"name": "Support Agent",
"description": "Resolves order questions using confirmed order data.",
"provider": "openai",
"model": "gpt-5-mini",
"maxTokens": 4000,
"outputType": "text"
}
```
### `agent/instructions.md`
Contains stable behavior: role, boundaries, decision rules, and guidance for tools. Keep changing user input out of this file and pass it to `run()` instead.
```md
You help customers understand their orders.
Always look up an order before making claims about its status.
Never invent order data.
```
Prompt variables use `{{ variableName }}` and are supplied once when the session is created.
## `actions/`
Actions let the model do work. Every direct child folder has metadata in `index.json`. Local actions also have executable `index.js`.
```text
actions/
lookupOrder/
index.json
index.js
```
- Omit `execution` for a local action.
- Use `"execution": "client"` when the caller must do the work.
- Direct child folders are discovered automatically.
## `skills/`
Skills are procedures loaded only when relevant:
```text
skills/
delayedOrderHandling/
index.json
instructions.md
```
`index.json` is the small discovery card. `instructions.md` is the full procedure. Orcha initially exposes only the card, keeping the base prompt small.
## `tests/`
Each direct child is one model-backed contract test:
```text
tests/
delayedOrder/
index.json
```
The test defines an input, action mocks, and deterministic expectations. The folder name is its CLI selector: `orcha test supportAgent/delayedOrder`.
## `evaluations/`
Each direct child configures an asynchronous model judge:
```text
evaluations/
supportQuality/
index.json
```
Evaluations score qualities such as grounding or clarity. Tests check deterministic contracts; evaluations check probabilistic quality.
## Generated `.orcha/`
`.orcha/` is generated output, not source:
```text
.orcha/
dist/
bundle.js
sessions/
supportAgent/
ses_...jsonl
.build/
.cli/
```
`dist/` is the production agent bundle. `.build/` and `.cli/` are temporary compiler artifacts. Do not edit or commit any of them. Access sessions through `agent.get()`, `history()`, `events()`, and `list()` rather than reading storage files directly.
## Discovery rules
- Agents and subagents must be registered in `orcha/index.ts`.
- Actions, skills, tests, and evaluations are discovered from direct child folders.
- Set `"enabled": false` in an item's `index.json` to keep work in progress inactive.
- Enabled entries must contain their required files.
- Model-facing names must be unique within an agent.
- Invalid files and schemas fail during `orcha dev` or `orcha build`, before a user run.
---
# Model Providers
Configure OrchaJS with OpenAI, Anthropic, DeepSeek, Gemini, Vertex AI, or Amazon Bedrock.
Source: https://orcha.sh/docs/model-providers
Markdown: https://orcha.sh/docs/model-providers.mdx
Configure providers once in `orcha/index.ts`, then select one in each agent's `index.json`.
## API-key providers
OpenAI, Anthropic, DeepSeek, and Google GenAI accept an API key string:
```ts
orcha.init({
providers: {
openai: process.env.OPENAI_API_KEY ?? "",
anthropic: process.env.ANTHROPIC_API_KEY ?? "",
deepseek: process.env.DEEPSEEK_API_KEY ?? "",
googlegenai: process.env.GOOGLE_API_KEY ?? "",
},
agents: {
assistant: "./assistant",
},
});
```
Use an object when you need a custom endpoint:
```ts
providers: {
openai: {
apiKey: process.env.OPENAI_API_KEY ?? "",
baseUrl: "https://api.openai.com/v1",
},
}
```
## Google Vertex AI
```ts
providers: {
vertexai: {
project: process.env.GOOGLE_CLOUD_PROJECT ?? "",
location: process.env.GOOGLE_CLOUD_LOCATION ?? "us-central1",
},
}
```
When `credentials` is omitted, the Google SDK uses Application Default Credentials.
For an explicit service account:
```ts
providers: {
vertexai: {
project: process.env.GOOGLE_CLOUD_PROJECT ?? "",
location: process.env.GOOGLE_CLOUD_LOCATION ?? "us-central1",
credentials: {
clientEmail: process.env.GOOGLE_CLIENT_EMAIL ?? "",
privateKey: process.env.GOOGLE_PRIVATE_KEY ?? "",
},
},
}
```
## Amazon Bedrock
```ts
providers: {
bedrock: {
region: process.env.AWS_REGION ?? "us-east-1",
},
}
```
When `credentials` is omitted, the AWS SDK uses its normal credential chain. Explicit credentials are also supported:
```ts
providers: {
bedrock: {
region: process.env.AWS_REGION ?? "us-east-1",
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "",
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? "",
sessionToken: process.env.AWS_SESSION_TOKEN,
},
},
}
```
## Select a provider and model
In the agent's `index.json`:
```json
{
"name": "Assistant",
"provider": "openai",
"model": "gpt-5-mini",
"outputType": "text"
}
```
`model` is the exact provider model identifier. Orcha does not rename models or translate `reasoningLevel` values between providers.
Different agents and evaluations may use different configured providers:
```text
assistant → OpenAI
policyReviewer → Anthropic
qualityJudge → Google Gemini
```
## Environment variables
The Orcha library reads the host application's existing `process.env`. Standalone CLI commands also load `.env` from the project root without overriding variables already present.
```bash
OPENAI_API_KEY=...
ANTHROPIC_API_KEY=...
DEEPSEEK_API_KEY=...
GOOGLE_API_KEY=...
```
Never place credentials in agent JSON, instructions, run metadata, prompt variables, tests, or session logs.
## Provider capabilities
Text is broadly supported. Structured output, reasoning controls, multimodal input, caching, and replay behavior vary by provider and model. Orcha normalizes supported behavior and returns a clear capability error instead of silently dropping unsupported input.
---
# Basic agent
Example of the simplest OrchaJS text chat agent with configuration and instructions.
Source: https://orcha.sh/docs/tutorial/basic-agent
Markdown: https://orcha.sh/docs/tutorial/basic-agent.mdx
## The simplest text chat agent
The project above is an example of the simplest text chat agent you can build
with Orcha. It has a model configuration, instructions, one registry entry,
and ordinary application code that runs it.
It can answer order-support questions from its instructions, but it cannot
look up real order data yet. Its instructions therefore prevent it from
inventing order details. The next tutorials add skills, actions, client
actions, and subagents to this same project.
Select any file in the editor to inspect the complete example.
## Understand each file
Next: [add a skill](/docs/tutorial/skills).
---
# Agent with skills
Example OrchaJS agent that loads specialized skill instructions only when they are relevant.
Source: https://orcha.sh/docs/tutorial/skills
Markdown: https://orcha.sh/docs/tutorial/skills.mdx
## Focused knowledge, loaded on demand
This example is a complete technical writing agent with one skill for
explaining engineering concepts. The base agent stays small. It initially sees
only the skill's name, description, and triggers.
When a request matches, the model loads the full procedure through Orcha's
internal `load_skill` tool. Orcha continues the same run automatically, and
the loaded instructions remain active for the durable session.
A skill is the right fit for policy, process, domain knowledge, or a repeatable
method. It guides the model but does not execute code.
Select any file in the editor to inspect the complete standalone project.
## Understand each file
Next: [build an agent that takes action](/docs/tutorial/actions).
---
# Agent that takes action
Example OrchaJS agent that calls APIs, databases, or any Node.js code as a local action.
Source: https://orcha.sh/docs/tutorial/actions
Markdown: https://orcha.sh/docs/tutorial/actions.mdx
## Let the agent do real work
This example is a complete order agent with one action: `lookup_order`. The
model receives a typed tool definition, chooses when to call it, and supplies
arguments that match the configured JSON Schema.
The action's `index.js` is ordinary application code. It can contain any
trusted Node.js logic: query your database, call an internal API, use an npm
package, invoke a third-party SDK, read from a service, or perform a
calculation. The in-memory order lookup here keeps the example runnable.
Orcha validates the model arguments, runs `index.js`, validates its return
value, gives that result back to the model, and continues until the agent
produces its final answer. Your application does not need to manage that tool
loop.
Select any file in the editor to inspect the complete standalone project.
## Understand each file
Next: [put a human in the loop](/docs/tutorial/client-actions).
---
# Human in the loop
Example OrchaJS human-in-the-loop agent that pauses for approval, then resumes.
Source: https://orcha.sh/docs/tutorial/client-actions
Markdown: https://orcha.sh/docs/tutorial/client-actions.mdx
## Move work into the caller
This example is a complete purchase approval agent. It can prepare the request,
but it cannot approve a purchase itself. The `request_human_approval` action
has `execution: "client"`, so Orcha describes the action to the model without
providing executable server code.
When the model requests approval, Orcha stores the request and pauses safely.
The application receives the action name, validated arguments, and a `callId`.
After the human decides, the application resumes that same session with the
result. The process can restart or the decision can happen much later; the
model context is already durable.
Human approval is only one client-action pattern. The same boundary can ask a
browser to upload a document, request a device location, open a confirmation
screen, collect a signature, or use any capability owned by the caller.
Select any file in the editor to inspect the complete standalone project.
## Understand each file
Next: [compose agents with subagents](/docs/tutorial/subagents).
---
# Agent with subagents
Example OrchaJS parent agent that delegates work to private subagents.
Source: https://orcha.sh/docs/tutorial/subagents
Markdown: https://orcha.sh/docs/tutorial/subagents.mdx
## Delegate focused reasoning
This example is a complete research coordinator with one private subagent. The
coordinator decides what to delegate, the researcher handles one focused
question, and the coordinator remains responsible for the final response.
A subagent is an ordinary agent folder with its own model configuration,
instructions, context, and durable session. Registering it inside
`coordinator.subagents` gives the parent internal tools to run, resume, and
inspect that child without exposing the child as a top-level application API.
The parent waits while the child runs, receives the child response as a tool
result, and continues automatically. Parent and child histories remain
separate and linked for inspection.
Select any file in the editor to inspect the complete standalone project.
## Understand each file
Next: [test an agent](/docs/tutorial/tests).
---
# Test an agent
Write OrchaJS agent tests with real model calls, mocked actions, and contract assertions.
Source: https://orcha.sh/docs/tutorial/tests
Markdown: https://orcha.sh/docs/tutorial/tests.mdx
## Protect the behavior that matters
This example is a complete order agent with one model-backed contract test.
The test runs the real compiled agent and provider while returning a fixed
response for `lookup_order`.
Mocking the action makes the data deterministic without replacing the model.
The expectations verify that the agent completed, called the correct action
with the exact order ID, and included confirmed facts in its response.
Each direct folder under `tests/` is one case. Run this case with:
```bash
npx orcha test orderAgent/delayedOrder
```
Unmocked local actions execute live, so mock operations that should not touch
real services during a test. Client actions must always be mocked.
Select any file in the editor to inspect the complete standalone project.
## Understand each file
Next: [evaluate an agent](/docs/tutorial/evaluations).
---
# Evaluate an agent
Add OrchaJS evaluations that score completed agent responses with a model judge.
Source: https://orcha.sh/docs/tutorial/evaluations
Markdown: https://orcha.sh/docs/tutorial/evaluations.mdx
## Measure quality, not exact wording
This example is a complete writing agent with an asynchronous model judge.
The agent answers with Anthropic, while the `response_quality` evaluation uses
OpenAI to score clarity and calibration independently.
Evaluations are for qualities that cannot be captured reliably by substring or
exact-value assertions. Every metric has a concrete criterion and an inclusive
threshold from 0 to 1.
Judging starts after a run completes. `execution.result` becomes available
without waiting, while `execution.evaluations` resolves when every enabled
judge has finished and its result has been stored.
Select any file in the editor to inspect the complete standalone project.
## Understand each file
Next: [deploy an agent](/docs/tutorial/production).
---
# Deploy to production
Deploy OrchaJS agents with your existing npm run build and production environment keys.
Source: https://orcha.sh/docs/tutorial/production
Markdown: https://orcha.sh/docs/tutorial/production.mdx
Your production workflow does not need a separate Orcha build configuration.
Use the build command your project already uses:
```bash
npm run build
```
Orcha is compiled and included as part of the application build. The same
agent folders and runtime API you used locally are used in production.
## Configure production credentials
Provide model-provider credentials through your deployment environment:
```bash
ANTHROPIC_API_KEY=...
```
Do not copy a local `.env` file into the production bundle.
## Deploy the application
Deploy the output of `npm run build` the same way you deploy the rest of your
Node.js application. No playground frontend is included in the production
output.
Application code remains unchanged:
```ts
const result = await orcha.assistant.run(
"Explain durable sessions.",
).result;
```
## Preserve durable sessions
The default Node storage writes sessions under `.orcha/sessions`. Use
persistent shared storage when a session must:
- survive a process or container restart,
- resume on another application instance,
- wait for a client action and continue later.
Read sessions through `get()`, `history()`, `events()`, and `list()` rather
than accessing storage files directly.
## Production checklist
- Run `npm run build` in CI.
- Run focused agent tests before deployment.
- Supply provider credentials through the production environment.
- Keep `.orcha/sessions` on persistent storage when sessions must resume.
- Save `sessionId` in your application database when users may return later.
- Await `execution.evaluations` in short-lived jobs when scores must finish
before the process exits.
---
# Start a session
Start an OrchaJS durable session with agent.run() and read sessionId, stream, and result.
Source: https://orcha.sh/docs/sessions/start
Markdown: https://orcha.sh/docs/sessions/start.mdx
Every `.run()` starts a new durable session. Orcha saves its messages, tool
calls, results, and usage automatically.
```ts
const run = orcha.supportAgent.run("Help me resolve order ord_1001.");
const result = await run.result;
if (result.status === "completed") {
console.log(result.output);
}
```
Save `run.sessionId` when the user may continue this conversation later.
## Add session details
Use the object form to name a session or attach application data:
```ts
const run = orcha.supportAgent.run({
content: "Help me resolve order ord_1001.",
name: "Order ord_1001",
metadata: {
customerId: "cus_123",
priority: "high",
},
});
```
`name` makes the session recognizable in your UI. `metadata` lets your
application associate it with users, orders, workspaces, or other records.
## Read everything run returns
`.run()` returns an execution immediately. The model continues working in the
background.
```ts title="Destructure the execution"
const {
sessionId,
stream,
snapshot,
result,
evaluations,
} = orcha.supportAgent.run("Help me with my order.");
const finalResult = await result;
```
- `sessionId` — available immediately; save it to continue or inspect the
session.
- `stream` — a `ReadableStream` of live output and status snapshots.
- `snapshot` — the latest snapshot emitted by `stream`, or `undefined` before
the first one arrives.
- `result` — a promise for the final state of this run.
- `evaluations` — a separate promise for evaluations configured on the agent.
Now narrow `finalResult.status` before reading status-specific fields:
```ts
if (finalResult.status === "completed") {
const { sessionId, output, usage } = finalResult;
console.log(output);
}
```
## API reference
### Input
```ts
run(input: string | {
content: string | MessageContent | MessageContent[];
name?: string;
metadata?: Record;
variables?: Record;
clientCapabilities?: Array;
}): Execution
```
- `content` — the first user message. It can be text or supported multimodal
content.
- `name` — an optional human-readable session name.
- `metadata` — searchable application data. Do not store secrets here.
- `variables` — values for `{{ variableName }}` placeholders in the agent's
instructions. They are fixed when the session is created.
- `clientCapabilities` — client action names this caller can handle.
Calling `.run()` again creates a different session. Use
[`resume()`](/docs/sessions/resume) to continue an existing one.
### Execution
```ts
type Execution = {
sessionId: string;
stream: ReadableStream>;
snapshot: ExecutionSnapshot | undefined;
result: Promise>;
evaluations: Promise;
};
```
The stream can emit:
- `{ status: "streaming", sessionId, output }` while output is arriving.
- `{ status: "waiting_for_subagent", sessionId, childSessionId, childAgent }`
while a child agent is running.
- Any final result described below.
### Final result
```ts
type RunResult =
| {
status: "completed";
sessionId: string;
output: TOutput;
usage?: Usage;
}
| {
status: "waiting_for_client_action";
sessionId: string;
output?: TOutput;
usage?: Usage;
clientToolCalls: ClientToolCall[];
}
| {
status: "paused";
sessionId: string;
output?: TOutput;
usage?: Usage;
}
| {
status: "failed";
sessionId: string;
error: RunError;
};
```
- `output` — final text for a text agent or parsed data for a JSON agent. A
paused run can contain partial output.
- `clientToolCalls` — actions your client must resolve before the run can
continue.
- `usage` — token usage for the run.
- `error` — structured failure information.
```ts
type Usage = {
inputTokens: number;
outputTokens: number;
reasoningTokens: number | null;
cacheReadTokens: number;
cacheWriteTokens: number;
};
type RunError = {
code:
| "invalid_input"
| "unsupported_content_type"
| "unsupported_provider_capability"
| "session_not_found"
| "session_busy"
| "client_action_required"
| "missing_tool_results"
| "unknown_call_id"
| "invalid_tool_result"
| "action_result_conflict"
| "session_completed"
| "provider_error"
| "storage_error"
| "aborted"
| "execution_failed";
message: string;
retryable: boolean;
details?: Record;
};
```
### Evaluations
`execution.result` does not wait for evaluations. Await
`execution.evaluations` when your process needs the scores before exiting:
```ts
type EvaluationResult = {
name: string;
status: "passed" | "failed" | "error";
metrics: Array<{
name: string;
score: number;
threshold: number;
passed: boolean;
reasoning: string;
evidence: string[];
}>;
usage?: Usage;
durationMs: number;
error?: {
message: string;
};
};
```
---
# Resume a session
Resume an OrchaJS session with .resume(), including human-in-the-loop client actions.
Source: https://orcha.sh/docs/sessions/resume
Markdown: https://orcha.sh/docs/sessions/resume.mdx
Use `.resume()` with a saved `sessionId` to continue the same conversation:
```ts
const result = await orcha.supportAgent.resume(sessionId, {
content: "What should I do next?",
}).result;
```
Orcha loads the durable context automatically. Do not send previous messages
again.
## Run, resolve a client action, and resume
A client action moves work into your application. The following is the entire
flow in one place:
```ts
// 1. Start the session.
let result = await orcha.approvalAgent.run({
content: "Approve a $750 laptop.",
clientCapabilities: ["request_human_approval"],
}).result;
// 2. The agent paused and requested work from your client.
if (result.status === "waiting_for_client_action") {
const call = result.clientToolCalls[0];
if (call.name === "request_human_approval") {
// Resolve this in your UI, mobile app, worker, or other client.
const approved = await showApprovalDialog(call.arguments);
// 3. Return the result and continue the same run.
result = await orcha.approvalAgent.resume(result.sessionId, {
toolResults: [
{
callId: call.callId,
output: {
approved,
note: "Decision submitted by the user.",
},
},
],
}).result;
}
}
if (result.status === "completed") {
console.log(result.output);
}
```
Use `call.name` to identify the requested client action. `call.arguments`
matches that action's `parameters`; the returned `output` must match its
`outputSchema`.
For example, a location action can return the fields defined by its own
schema:
```ts
{
callId: call.callId,
output: {
latitude: 28.6139,
longitude: 77.209,
},
}
```
## Resolve multiple client actions
Return one result for every requested call in one `.resume()`:
```ts
if (result.status === "waiting_for_client_action") {
const toolResults = await Promise.all(
result.clientToolCalls.map(async (call) => {
const output = await handleClientAction(call.name, call.arguments);
return {
callId: call.callId,
output,
};
}),
);
const next = await orcha.supportAgent.resume(result.sessionId, {
toolResults,
}).result;
}
```
Every pending `callId` must appear exactly once.
## When a client action fails
Keep normal results simple. Add `isError: true` only when your client could not
perform the action:
```ts
{
callId: call.callId,
output: {
message: "The user denied location access.",
},
isError: true,
}
```
The agent receives that failure and can decide what to do next.
## API reference
### Continue the conversation
```ts
resume(
sessionId: string,
input?: string | {
content: string | MessageContent | MessageContent[];
clientCapabilities?: Array;
},
): Execution
```
- `sessionId` — the existing session to continue.
- `content` — the next user message.
- `clientCapabilities` — client actions available for this resumed run.
- Omitting `input` asks the agent to `"Continue."`.
A conversational resume starts a new numbered run in the same session.
### Resolve pending client actions
```ts
resume(
sessionId: string,
input: {
toolResults: Array<{
callId: string;
output: ClientActionOutput;
isError?: boolean;
}>;
},
): Execution
```
- `callId` — copy it unchanged from the requested call.
- `output` — data matching that client action's `outputSchema`.
- `isError` — optional; use `true` only when the client action failed.
Do not combine `content` and `toolResults`. While actions are pending, resolve
them before sending another conversational message.
### Requested call
```ts
type ClientToolCall = {
callId: string;
name: string;
arguments: Record;
};
```
- `callId` uniquely pairs the request with its result.
- `name` is the client action name from its `index.json`.
- `arguments` matches the action's `parameters` schema.
### Result
`.resume()` returns the same `Execution` and `RunResult` shapes as
[`run()`](/docs/sessions/start):
- `completed` — read `result.output`.
- `waiting_for_client_action` — resolve the new `clientToolCalls`.
- `paused` — the session was explicitly paused.
- `failed` — inspect `result.error`.
Common client-action errors include missing results, an unknown or duplicated
`callId`, output that does not match the action schema, and trying to send
content while actions remain pending.
---
# Read a session
Read an OrchaJS session snapshot with .get() for status, output, and pending client actions.
Source: https://orcha.sh/docs/sessions/get
Markdown: https://orcha.sh/docs/sessions/get.mdx
Use `.get()` to read the latest session state without starting another run:
```ts
const session = await orcha.supportAgent.get(sessionId);
console.log(session.status);
console.log(session.lastOutput);
```
This is useful when restoring a page after a refresh, checking background
work, or finding a pending client action.
## Example snapshot
```ts
{
sessionId: "ses_01K...", // The durable session ID.
agent: "supportAgent", // Registered agent key.
name: "Order ord_1001", // Optional display name.
status: "active", // Overall session state.
metadata: { customerId: "cus_123" }, // Application data you attached.
createdAt: "2026-09-28T12:00:00Z", // ISO creation time.
updatedAt: "2026-09-28T12:01:12Z", // ISO time of the latest event.
runStatus: "completed", // State of the latest run.
pendingClientActions: [], // Client actions still waiting.
lastOutput: "Your order has shipped.", // Latest assistant output.
usage: { // Latest run token usage.
inputTokens: 320,
outputTokens: 42,
reasoningTokens: null,
cacheReadTokens: 0,
cacheWriteTokens: 0,
},
}
```
## Restore a pending action
```ts
const session = await orcha.supportAgent.get(sessionId);
if (session.runStatus === "waiting_for_client_action") {
const call = session.pendingClientActions[0];
console.log(call.name, call.arguments);
}
```
Resolve it with [`resume()`](/docs/sessions/resume).
## API reference
```ts
get(sessionId: string): Promise
type SessionSnapshot = {
sessionId: string;
agent: string;
name?: string;
status: "active" | "paused" | "completed";
metadata: Record;
createdAt: string;
updatedAt: string;
runStatus?:
| "running"
| "waiting_for_subagent"
| "waiting_for_client_action"
| "paused"
| "completed"
| "failed";
pendingClientActions: ClientToolCall[];
lineage?: {
origin: "delegated";
parentAgent: string;
parentSessionId: string;
parentCallId: string;
};
lastOutput?: AgentOutput;
usage?: Usage;
};
type ClientToolCall = {
callId: string;
name: string;
arguments: Record;
};
type Usage = {
inputTokens: number;
outputTokens: number;
reasoningTokens: number | null;
cacheReadTokens: number;
cacheWriteTokens: number;
};
```
### Status fields
`status` describes the durable session:
- `active` — available, waiting for a client action, or currently running.
- `paused` — explicitly paused with `.pause()`.
- `completed` — its lifecycle is complete.
`runStatus` describes only the latest run:
- `running` — the model is working.
- `waiting_for_subagent` — a child agent is working.
- `waiting_for_client_action` — your client must return tool results.
- `paused` — work was explicitly paused.
- `completed` — the latest run finished normally.
- `failed` — the latest run failed.
### Optional fields
- `lineage` exists on delegated subagent sessions and points back to the
parent.
- `lastOutput` is text for text agents or parsed data for JSON agents.
- `usage` can be absent before the session has recorded model usage.
- `runStatus` can be absent before the first run starts.
`.get()` throws `session_not_found` when the ID does not belong to this
registered agent.
---
# Read conversation history
Render OrchaJS conversation history with .history() for messages, actions, and skills.
Source: https://orcha.sh/docs/sessions/history
Markdown: https://orcha.sh/docs/sessions/history.mdx
Use `.history()` to render a conversation in your application:
```ts
const history = await orcha.supportAgent.history(sessionId, {
page: 1,
pageSize: 25,
});
for (const item of history.items) {
if (item.type === "message") {
console.log(item.role, item.content);
}
if (item.type === "client_action") {
console.log(item.name, item.callId, item.status);
}
}
```
`history()` removes low-level provider bookkeeping. Its items represent
messages and useful agent activity such as actions, skills, subagents, and
evaluations.
## Example response
```ts
{
items: [
{
id: "message:3", // Stable item ID.
type: "message", // How to interpret this item.
createdAt: "2026-09-28T12:00:04Z", // ISO timestamp.
role: "user", // "user" or "assistant".
content: [
{ type: "text", text: "Where is my order?" },
],
},
{
id: "client-action:call_123",
type: "client_action",
createdAt: "2026-09-28T12:00:09Z",
name: "request_human_approval",
callId: "call_123",
status: "waiting",
arguments: { amount: 750, currency: "USD" },
summary: "request human approval is waiting for the client.",
},
],
page: 1, // Current page.
pageSize: 25, // Maximum items on this page.
total: 2, // Total projected history items.
hasMore: false, // Whether an older page exists.
// The current SessionSnapshot is also included here.
sessionId: "ses_01K...",
agent: "supportAgent",
status: "active",
metadata: {},
createdAt: "2026-09-28T12:00:00Z",
updatedAt: "2026-09-28T12:00:09Z",
runStatus: "waiting_for_client_action",
pendingClientActions: [
{
callId: "call_123",
name: "request_human_approval",
arguments: { amount: 750, currency: "USD" },
},
],
}
```
## Pagination
Page 1 contains the newest page. Higher page numbers move backward through
the session:
```ts
const older = await orcha.supportAgent.history(sessionId, {
page: 2,
pageSize: 50,
});
```
Use [`events()`](/docs/sessions/events) when you need the canonical event log
instead of a user-facing history.
## API reference
```ts
history(
sessionId: string,
options?: {
page?: number;
pageSize?: number;
},
): Promise
type SessionHistory = SessionSnapshot & {
items: SessionHistoryItem[];
page: number;
pageSize: number;
total: number;
hasMore: boolean;
};
```
- `page` defaults to `1`.
- `pageSize` defaults to `50` and accepts `1` through `100`.
- Pages are newest-first: page 2 is older than page 1.
- Snapshot fields describe the session at the time of the request.
### History item
```ts
type SessionHistoryItem = {
id: string;
type:
| "message"
| "action"
| "client_action"
| "subagent"
| "skill"
| "evaluation"
| "session_completed";
createdAt: string;
role?: "user" | "assistant";
content?: MessageContent[];
name?: string;
status?: "running" | "waiting" | "paused" | "completed" | "failed";
summary?: string;
callId?: string;
childSessionId?: string;
arguments?: Record;
durationMs?: number;
usage?: Usage;
metrics?: EvaluationMetric[];
};
```
All items contain `id`, `type`, and `createdAt`. Other fields depend on
`type`:
- `message` — `role`, `content`, and assistant `usage` when available.
- `action` — `name`, `callId`, `status`, `arguments`, `durationMs`, and
`summary` as available.
- `client_action` — `name`, `callId`, `status`, pending `arguments`, and
`summary`.
- `subagent` — `name`, `childSessionId`, `callId`, `status`, `usage`, and
`summary`.
- `skill` — `name`, `status`, and `summary`.
- `evaluation` — `name`, `status`, `metrics`, `durationMs`, and `summary`.
- `session_completed` — completion `status` and `summary`.
### Message content
```ts
type MessageContent =
| { type: "text"; text: string }
| {
type: "image" | "video" | "audio" | "url";
mimeType: string;
fileUri: string;
}
| {
type: "file";
filePath: string;
mimeType: string;
};
```
---
# List sessions
List OrchaJS durable sessions with .list() and filter by status or metadata.
Source: https://orcha.sh/docs/sessions/list
Markdown: https://orcha.sh/docs/sessions/list.mdx
Use `.list()` to show sessions created by one registered agent:
```ts
const sessions = await orcha.supportAgent.list({
page: 1,
pageSize: 25,
});
for (const session of sessions.items) {
console.log(session.name, session.status);
}
```
## Filter sessions
Find paused sessions:
```ts
const paused = await orcha.supportAgent.list({
status: "paused",
});
```
Find sessions attached to one application record:
```ts
const customerSessions = await orcha.supportAgent.list({
metadata: {
customerId: "cus_123",
},
});
```
Filters can be combined:
```ts
const work = await orcha.supportAgent.list({
status: "active",
metadata: {
customerId: "cus_123",
priority: "high",
},
});
```
## Example response
```ts
{
items: [
{
sessionId: "ses_01K...",
agent: "supportAgent",
name: "Order ord_1001",
status: "active",
metadata: { customerId: "cus_123" },
createdAt: "2026-09-28T12:00:00Z",
updatedAt: "2026-09-28T12:04:00Z",
runStatus: "completed",
pendingClientActions: [],
lastOutput: "Your order has shipped.",
usage: {
inputTokens: 320,
outputTokens: 42,
reasoningTokens: null,
cacheReadTokens: 0,
cacheWriteTokens: 0,
},
},
],
page: 1, // Current page.
pageSize: 25, // Maximum items on this page.
total: 1, // Sessions matching the filters.
hasMore: false, // Whether another page exists.
}
```
## API reference
```ts
list(options?: {
page?: number;
pageSize?: number;
status?: "active" | "paused" | "completed";
metadata?: Record;
}): Promise
type SessionList = {
items: SessionSnapshot[];
page: number;
pageSize: number;
total: number;
hasMore: boolean;
};
```
- `page` defaults to `1`.
- `pageSize` defaults to `50` and accepts `1` through `100`.
- `status` matches the durable session status, not `runStatus`.
- `metadata` matches sessions containing the supplied key-value pairs.
- `items` contains complete
[`SessionSnapshot`](/docs/sessions/get) objects.
- `total` is the total number matching the filters, not just this page.
- `hasMore` indicates whether the next page exists.
`.list()` is scoped to the registered agent it is called on.
`orcha.supportAgent.list()` does not return sessions owned by another
top-level agent.
---
# Update a session
Update an OrchaJS session name or metadata with .update() without starting a new run.
Source: https://orcha.sh/docs/sessions/update
Markdown: https://orcha.sh/docs/sessions/update.mdx
Use `.update()` to change the name or application metadata of a session:
```ts
const session = await orcha.supportAgent.update(sessionId, {
name: "Escalated order ord_1001",
metadata: {
priority: "urgent",
assignedTeam: "fulfillment",
},
});
```
The returned value is the updated
[`SessionSnapshot`](/docs/sessions/get).
## Update one field
Metadata is merged, so you only need to send fields that changed:
```ts
const session = await orcha.supportAgent.update(sessionId, {
metadata: {
priority: "resolved",
},
});
console.log(session.metadata);
// {
// customerId: "cus_123", Existing value remains.
// priority: "resolved", Supplied value is updated.
// }
```
Use `null` as an application-level empty value:
```ts
await orcha.supportAgent.update(sessionId, {
metadata: {
assignedTeam: null,
},
});
```
This sets the value to `null`; it does not remove the key.
## API reference
```ts
update(
sessionId: string,
update: {
name?: string;
metadata?: Record;
},
): Promise
```
- `sessionId` — the existing session to update.
- `name` — replaces the current display name.
- `metadata` — shallowly merges supplied keys into existing metadata.
- At least one of `name` or `metadata` is required.
- Metadata values must be strings, finite numbers, booleans, or `null`.
- The promise resolves with the complete updated snapshot.
Every successful update appends a durable `session.updated` event. Updating
name or metadata does not start a run, send a model request, or alter the
conversation.
Do not store secrets in session metadata.
---
# Pause a session
Pause an OrchaJS session with .pause() and continue the same durable conversation later.
Source: https://orcha.sh/docs/sessions/pause
Markdown: https://orcha.sh/docs/sessions/pause.mdx
Use `.pause()` to safely stop active work:
```ts
const session = await orcha.supportAgent.pause(sessionId);
console.log(session.status);
// "paused"
```
Orcha preserves what happened before the pause. You can continue the same
session later.
## Continue later
```ts
const result = await orcha.supportAgent.resume(sessionId, {
content: "Continue, but keep the answer under three bullets.",
}).result;
if (result.status === "completed") {
console.log(result.output);
}
```
If the session is waiting for a client action, return its tool results
instead. A new message cannot skip pending client actions.
## What gets paused
- Active provider work is aborted.
- Active child-agent work is paused too.
- Streamed output is preserved as an incomplete assistant message.
- `run.paused` and `session.paused` events are recorded.
- The returned snapshot has `status: "paused"` and `runStatus: "paused"`.
Calling `.pause()` on an already paused session safely returns its current
snapshot.
## API reference
```ts
pause(sessionId: string): Promise
```
- `sessionId` — the session to stop.
- The promise waits until active work has stopped and durable pause events
have been saved.
- It resolves with the complete
[`SessionSnapshot`](/docs/sessions/get).
- Calling it again is idempotent: an already paused session returns its
current snapshot.
- `session_not_found` is thrown when the ID does not belong to this agent.
Pausing does not delete the session or its output. Resume it with
[`resume()`](/docs/sessions/resume).
---
# Debug, audit, and replay
Read OrchaJS JSONL session events with .events() for debugging, audit, and replay.
Source: https://orcha.sh/docs/sessions/events
Markdown: https://orcha.sh/docs/sessions/events.mdx
Use `.events()` when you need the exact durable record for auditing,
debugging, or replay:
```ts
const page = await orcha.supportAgent.events(sessionId, {
page: 1,
pageSize: 100,
});
for (const event of page.events) {
console.log(event.sequence, event.type, event.data);
}
```
These are the pure events stored by the default Node runtime at:
```text
.orcha/sessions//.jsonl
```
This append-only event stream is not just a debug log. Orcha derives the
agent's functioning session state, history, pending client actions, usage,
and resumable context from it.
Use `.history()` for normal conversation UI. Use `.events()` when the exact
internal timeline matters.
## Example response
```ts
{
events: [
{
sequence: 1, // Position in this session.
type: "session.created", // What happened.
timestamp: "2026-09-28T12:00:00Z", // ISO timestamp.
data: {
schemaVersion: 1,
sessionId: "ses_01K...",
agent: "supportAgent",
status: "active",
metadata: {},
variables: {},
},
},
{
sequence: 2,
type: "run.started",
timestamp: "2026-09-28T12:00:01Z",
run: 1, // Numbered run in the session.
data: {
status: "running",
agent: "supportAgent",
provider: "anthropic",
model: "claude-sonnet-4-6",
region: "global",
outputType: "text",
clientCapabilities: [],
},
},
],
throughSequence: 12, // Stable upper boundary for pagination.
page: 1,
pageSize: 100,
total: 12,
hasMore: false,
// The current SessionSnapshot is included too.
sessionId: "ses_01K...",
agent: "supportAgent",
status: "active",
metadata: {},
createdAt: "2026-09-28T12:00:00Z",
updatedAt: "2026-09-28T12:00:08Z",
runStatus: "completed",
pendingClientActions: [],
}
```
## Paginate against a stable session
Sessions can receive new events while you read older pages. Keep the
`throughSequence` returned by the first request and send it with later pages:
```ts
const latest = await orcha.supportAgent.events(sessionId, {
page: 1,
pageSize: 100,
});
const older = await orcha.supportAgent.events(sessionId, {
page: 2,
pageSize: 100,
throughSequence: latest.throughSequence,
});
```
This keeps every page within the same event boundary. Page 1 is the newest
page; higher page numbers move backward.
Most product interfaces should use [`history()`](/docs/sessions/history)
instead. Do not read `.orcha` storage files directly.
## API reference
```ts
events(
sessionId: string,
options?: {
page?: number;
pageSize?: number;
throughSequence?: number;
},
): Promise
type SessionEvents = SessionSnapshot & {
events: SessionEvent[];
throughSequence: number;
page: number;
pageSize: number;
total: number;
hasMore: boolean;
};
```
- `page` defaults to `1`.
- `pageSize` defaults to `50` and accepts `1` through `100`.
- `throughSequence` fixes the newest event included across paginated calls.
- `total` counts events inside that sequence boundary.
- Snapshot fields describe the current session.
### Event envelope
```ts
type SessionEvent = {
sequence: number;
type: SessionEventType;
timestamp: string;
run?: number;
data: Record;
};
```
- `sequence` is unique and strictly ordered within one session.
- `type` identifies the event and the shape of `data`.
- `timestamp` is an ISO timestamp.
- `run` identifies the numbered run. Session-level events omit it.
- `data` is the typed payload for that event.
### Event types
Session lifecycle:
```ts
"session.created"
"session.updated"
"session.paused"
"session.resumed"
```
Run lifecycle:
```ts
"run.started"
"run.paused"
"run.completed"
"run.failed"
```
Messages and actions:
```ts
"message.created"
"action.requested"
"action.completed"
"action.failed"
"client_action.requested"
"client_action.resolved"
```
Skills, evaluations, and subagents:
```ts
"skill.requested"
"skill.loaded"
"skill.failed"
"evaluation.requested"
"evaluation.completed"
"evaluation.failed"
"subagent.initiated"
"subagent.resumed"
"subagent.completed"
"subagent.paused"
"subagent.failed"
```
Tests can additionally write `test.warning` and `test.completed`.
### Important payloads
```ts
// message.created
{
role: "user" | "assistant" | "tool";
content: MessageContent[] | ToolResult[];
// Assistant messages can also include provider, model, usage,
// durationMs, stopReason, responseId, status, and parsedOutput.
}
// client_action.requested
{
status: "waiting";
calls: Array<{
callId: string;
name: string;
arguments: Record;
}>;
localResults: ToolResult[];
toolCallOrder: string[];
}
// client_action.resolved
{
status: "completed";
results: ToolResult[];
}
// run.paused
{
status: "waiting_for_client_action" | "paused";
clientToolCalls?: ClientToolCall[];
output?: AgentOutput;
usage?: Usage;
durationMs?: number;
}
// run.failed
{
status: "failed";
durationMs: number;
usage?: Usage;
error: {
code: string;
message: string;
retryable?: boolean;
};
}
```
Treat the event log as append-only. Consume events by `sequence`; never edit
or infer storage filenames.
---
# CLI
OrchaJS CLI reference for init, playground, run, test, and production builds.
Source: https://orcha.sh/docs/cli
Markdown: https://orcha.sh/docs/cli.mdx
Run commands through `npx orcha` or package scripts.
## `orcha init`
```bash
npx orcha init
```
Adds a minimal `orcha/` registry, an example agent, `AGENTS.md`, and the `.orcha/` gitignore entry. Existing files are skipped, not overwritten.
## `orcha dev`
```bash
npx orcha dev
```
Validates the registry and watches `orcha/**`. This is offline and does not call a model.
## `orcha playground`
```bash
npx orcha playground
npx orcha playground --host localhost --port 4310 --no-open
```
Starts the local development UI. Defaults to `localhost:4310` and opens the browser.
## `orcha run`
Start a session:
```bash
npx orcha run orderSupport --input "Where is ord_1001?"
```
Use structured or multimodal input from a file:
```bash
npx orcha run orderSupport --input-file request.json
```
Continue a session:
```bash
npx orcha run orderSupport \
--session ses_123 \
--input "What should I do next?"
```
Submit client-action results:
```bash
npx orcha run orderSupport \
--session ses_123 \
--tool-results tool-results.json
```
`tool-results.json`:
```json
[
{
"callId": "call_123",
"output": {
"approved": true,
"note": "Approved by support lead"
}
}
]
```
Add `--json` for machine-readable `{ result, evaluations }` output.
## `orcha test`
```bash
npx orcha test
npx orcha test orderSupport
npx orcha test orderSupport/delayedOrder
npx orcha test orderSupport/delayedOrder --json
```
Tests call real providers and may consume tokens. Unmocked local actions execute live.
## `orcha build`
```bash
npx orcha build
```
Performs offline production compilation and writes `.orcha/dist/bundle.js`. It does not call a provider.
## Suggested scripts
```json
{
"scripts": {
"dev": "orcha playground",
"build": "orcha build",
"test": "orcha test",
"orcha:dev": "orcha dev",
"orcha:test": "orcha test"
}
}
```