A TypeScript runtime for chat agents, one-shot tasks, and agent teams. It records each run so you can measure changes against real pass/fail checks and improve the agent without changing your product integration.
Domain behavior (models, tools, knowledge) plugs in as adapters; the scoring statistics and the ship decision come from @tangle-network/agent-eval; sandboxed execution from @tangle-network/sandbox.
pnpm add @tangle-network/agent-runtime @tangle-network/agent-eval @tangle-network/sandboxNew here? Read docs/concepts.md for the mental model in plain terms, then pick a front door below.
One agent attempt, run by a loop you control.
This is examples/quickstart/minimal.ts in full: it compiles and runs as pasted, with no credentials.
import type { AgentProfile } from '@tangle-network/agent-interface'
import {
inProcessSandboxClient,
runAgentRounds,
type TerminalDecision,
} from '@tangle-network/agent-runtime/kernel'
import type { SandboxEvent } from '@tangle-network/sandbox'
const profile = {
name: 'note-writer',
harness: 'cli-base',
model: { provider: 'scripted', default: 'scripted/note-writer' },
} satisfies AgentProfile
// A scripted worker. Swap in a sandbox, CLI-harness, or router backend later.
const worker = inProcessSandboxClient({
onPrompt: (): SandboxEvent[] => [
{ type: 'result', data: { result: { note: 'Shipped one-click restore.' } } },
],
})
const result = await runAgentRounds({
task: 'Write a one-line release note for one-click restore.',
driver: {
// plan returns the tasks to run this iteration; [] means no more work.
plan: async (task, history) => (history.length === 0 ? [task] : []),
// 'done' is one of the four kernel keywords in TERMINAL_DECISIONS.
decide: (): TerminalDecision => 'done',
},
agentRun: { profile, taskToPrompt: (t) => t },
output: { parse: (events) => events },
ctx: { sandboxClient: worker },
})
console.log(`decision: ${result.decision} — ${result.iterations.length} iteration(s)`)Run it from a clone of this repo and you get exactly this:
$ pnpm i && pnpm build
$ pnpm tsx examples/quickstart/minimal.ts
decision: done — 1 iteration(s)examples/quickstart grows the same call into a loop that reads each output and writes the next prompt from it.
Five words appear everywhere:
| Word | What it means |
|---|---|
| worker | An agent that produces an answer. Here it is a SandboxClient. |
| driver | Your code. It runs a worker, reads the output, and writes the next prompt. |
| decision | What decide returns. The four keywords in TERMINAL_DECISIONS (stop, pick-winner, fail, done) end the loop; every other value is your own vocabulary and continues it. |
| verdict | What a validator returns: valid or not, with a score. |
| harness | What drives an agent. cli-base is the router-backed mode with no coding agent behind it; claude-code, codex, and opencode each run a real coding CLI. |
One row per entry point, ordered by how often real products use it. Each row links to a runnable example.
| Front door | When to call it | What you give it | What you get back |
|---|---|---|---|
runAgentTaskStream · example |
You run one agent turn and read its events yourself. | a task, a backend, a message | an async stream of RuntimeStreamEvent |
handleChatTurn (/durable) · example |
A web route must stream one turn to a browser and save the reply. | how to produce tokens, how to persist | an HTTP body plus a persist call after the last token |
AgentExecutionBackend · example |
You choose where the tokens come from: your loop, a sandbox, or an exact profile. | kind plus a stream() generator |
the same event union from any source |
runToolLoop (/tool-loop) · example |
The model must call your tools and answer in the same turn. | one model turn, your executors | final text, every tool outcome, a stop reason |
startRuntimeRun · example |
You must record what a run cost and whether it succeeded. | run identity, a store adapter | a live cost tally and one persisted row |
runAgentRounds (/kernel) · example |
One prompt is not enough, and your code owns the stop rule. | plan, decide, an output adapter, a sandbox client |
every attempt, the verdicts, and a winner |
supervise (/kernel) · example |
A model must decide the plan and drive other agents. | a supervisor profile, a goal, a budget | the delivered result, or a typed reason and the spend |
startRetainedRun (/kernel) · example |
The job must outlive the process that started it. | a provider, keys, a durable admission hook | a claim ticket any process can reattach to |
improve · example |
You must change one part of an agent and prove the gain. | a profile field, three case sets, a judge | a detached candidate, a lift interval, ship or hold |
Five mechanisms continue interrupted work. Pick by what died.
- The HTTP connection — call
streamPromptagain with the sameexecutionId. - Nothing, but you want the same box for the next turn —
openSandboxRun. - The coordinator process, mid-orchestration —
supervise({ runDir }). - The user's chat session — the
/conversationstore adapters. - Everything except the provider — retained runs.
- Benchmarks and leaderboards — compare strategies with significance stats (
runBenchmark), or stand up a harness×model board (defineLeaderboard):examples/coding-benchmark,examples/webcode-matrix. - Agent graphs — fixed topologies authored as data and run through
runGraph:examples/graphs. - Improve a knowledge base — a measured candidate copy of a KB, wiki, or RAG corpus:
docs/improve.md. - PrimeIntellect — package the same runtime program as a Verifiers environment:
docs/primeintellect.md. - Conversations (
/conversation) — multi-turn two-agent sessions with SQL-backed resume. - MCP servers (
/mcp) — give any agent adelegatetool plus live coordination tools. - Live run view (
/tui) —agent-runtime-topshows every supervisor run in a workspace, with steer and cancel. - Telemetry — every loop emits
loop.*trace events, exported as OpenTelemetry GenAI spans whenOTEL_EXPORTER_OTLP_ENDPOINTis set.
All 33 examples live in examples/.
- Roles are configuration. Driver, worker, and coordinator describe what an agent does in a run. They are not separate agent types.
- Runs are recorded. A run can report tokens, dollars, time, outputs, and scores.
- Candidates face fresh tasks. The optimizer uses train and selection tasks. Promotion uses a separate final set.
- Scores come from executed attempts. Runtime recomputes results from the recorded cells and rejects incomplete cost or source evidence.
docs/concepts.md, the mental model in plain terms.docs/canonical-api.md, find the primitive: "I want to ___ → use ___".docs/api/primitive-catalog.md, every export in one generated, never-stale list with its import path. Check it before building anything new.docs/improve.md, the improvement reference: optimizers, surfaces, redaction, proposal, review, activation.docs/STABILITY.md, what@stableand@experimentalpromise you, and how a symbol graduates.docs/design.md, the design philosophy and the research behind it: background reading, not required to use the package.bench/HARNESS.md, the experiment harness and how to run a benchmark.
Contributing: pnpm i && pnpm build && pnpm test gets you running; the full local gate is the package.json scripts (lint, typecheck, docs:check).