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.

Audience · engineers building agents Needs · an OpenAI API key (stays in this browser) Package · @animahealth/adk (MIT)

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.