Agent Development Kit · Start · start here
Build an agent, run it in this page
The ADK is a TypeScript framework for production multi-agent systems: schema-first, event-sourced, provider-agnostic. The cells below are live editors running the shipped runtime. Paste your OpenAI key, press Run, edit anything, run again. Steps 1 to 3 go to OpenAI; the testing aside runs the same code with the model scripted. No key handy? The cells read as plain code, and everything they print is described beside them.
Your key
Paste a key, run everything
This site is static — no backend, no proxy. Your key lives in this browser's localStorage and
requests go straight to api.openai.com, exactly as they would from your own
machine.
Step 1
An agent with a tool
The whole program: one tool with a Zod schema, one agent that carries it, one run. The model
reads the tool's description and decides to call it. Your execute computes the
answer in this page. This is the same code you would run locally after
npm install @animahealth/adk. Building costs nothing and needs no key: this cell
prints the agent's name.
import { adk } from '@animahealth/adk'
import { openai } from '@animahealth/adk/openai'
import { z } from 'zod'
const app = adk()
const calculator = app.tool({
name: 'calculate',
description: 'Evaluate a mathematical expression',
schema: z.object({ expression: z.string() }),
execute: (ctx) => {
const sanitized = ctx.args.expression.replace(/[^\d\s+*/().-]/g, '')
return { result: Function(`"use strict"; return (${sanitized})`)() }
},
})
const assistant = app.agent({
name: 'math_assistant',
model: openai('gpt-5.6-luna'),
context: [app.context.system('Use the calculator for arithmetic.'), app.context.history()],
tools: [calculator],
})
assistant.name
Now run it. The model chooses to call the calculator, and your code does the arithmetic. What prints is one short assistant sentence carrying the computed number. Edit the question and run again.
const run = await app.run(assistant, 'What is 731 * 268, minus 17?')
run.output.text
Step 2
What it cost
Nothing about a run is opaque. Tokens, model calls, and cost come straight off the run's
model_end events. This cell reads the run bound in step 1, so that
cell has to have been pressed, with a key. It prints a usage object: input and output token
counts, two model calls, and an estimated cost.
run.usage
Step 3
The ledger the run left behind
Everything the agent did is an append-only event history. It belongs to the
session, not to the run: a run is one pass over it. So the full ledger is
run.session.events, and run.stepEvents is this run's slice of it.
This cell reads the same run from step 1. Note the tool_call and
tool_result pair: the model decided, your code executed. Each
model_start/model_end pair brackets one model call. A tool-using
turn makes two round-trips — one to decide the call, one to answer with its result — which is
why run.usage reports two model calls. On a reasoning model, the summary lands as
a thought event.
run.session.events.map((event) => event.type)
Aside
Testing the same agent, no key
The test kit replaces only the model with scripted turns. The tool still executes and the ledger still accrues. So agent tests run deterministically in CI, with no credentials. This cell needs the build cell from step 1 pressed once, and no key at all. It prints the tool results the scripted run produced. Skip it if you only came to build.
import { getToolResults, runTest, user, model } from '@animahealth/adk/testing'
// The assistant from step 1, with the model's turns scripted: the script decides THAT the
// calculator is called; the calculator itself really runs.
const test = await runTest(assistant, [
user('What is 134 divided by 4?'),
model({ toolCalls: [{ name: 'calculate', args: { expression: '134 / 4' } }] }),
model('134 divided by 4 is 33.5.'),
])
getToolResults(test.events)
Where to go next
Three doors out of here
Every chapter behind this one teaches the same way: by running the code.
- Get it on your machine. The next hour moves this program into your editor, recipe by recipe.
- See an agent stop and ask a human. The Bookings sample pauses mid-run and resumes from a stored session.
- Understand what you just ran. Five primitives and one ledger names every shape the runner executes.