Agent Development Kit · Start

Ask a booking agent. Watch it use a tool.

A live model reads your request, decides whether to look up a booking, and answers with the result. Your tool updates typed application state. Run it, change the question, and inspect the state and tool calls it produced.

Live OpenAI model Synthetic booking data Runs in your browser

Connect your model.

Save an OpenAI API key, then run the cells in order or press Run all. Requests go directly from this browser to api.openai.com and incur provider usage. The key stays in this browser's localStorage until you clear it. The booking data is fictional; the model calls are live.

Explore the runtime without a key using the separate scripted test example.

Step 1

Define what the application remembers.

One schema types every ctx.state read and write. The tool looks up a booking and records its reference and slot. Building these definitions does not call a model.

import { adk } from '@animahealth/adk'
import { z } from 'zod'

const app = adk({
	schema: {
		session: {
			reference: z.string().default(''),
			slot: z.string().nullable().default(null),
		},
	},
})

const bookings: Record<string, string> = {
	'B-42': 'Tuesday at 14:30',
	'B-73': 'Friday at 09:00',
}
const lookupBooking = app.tool({
	name: 'lookup_booking',
	description: 'Look up an appointment by its booking reference.',
	schema: z.object({ reference: z.string() }),
	execute: (ctx) => {
		ctx.state.reference = ctx.args.reference
		ctx.state.slot = bookings[ctx.args.reference] ?? null
		return { reference: ctx.state.reference, slot: ctx.state.slot }
	},
})

lookupBooking.name

Step 2

Choose what the model sees.

The agent gets instructions, the last lookup from typed state, and conversation history. Context is rebuilt before each model call, so the next call sees state written by the tool.

import { openai } from '@animahealth/adk/openai'

const assistant = app.agent({
	name: 'booking-assistant',
	model: openai('gpt-5.6-luna'),
	context: [
		app.context.system(({ state }) =>
			'Help with booking questions. Look up references before giving appointment times. ' +
			'If the reference is missing, ask for it. A null slot means no booking was found. ' +
			`Last lookup: ${state.reference || 'none'}. Slot: ${state.slot ?? 'none'}.`,
		),
		app.context.history(),
	],
	tools: [lookupBooking],
})

assistant.name

Step 3

Let the model decide what to do.

Run this cell to make a live request. The agent should call lookup_booking for B-42 and answer with Tuesday at 14:30. Its wording can vary. Nothing in the script supplies a model response or tells the runner which tool to call.

const question = 'What time is booking B-42?'
const run = await app.run(assistant, {
	input: { message: question, initialState: { session: {} } },
})

run.output.text

Change B-42 to B-73 for a different appointment. Try B-99 for a missing booking, or “When is my appointment?” to see whether the agent asks for a reference. Each run starts a new session, so you can compare the choices without earlier conversation influencing them.

Step 4

Read the state and the tool events.

For B-42, expect reference: "B-42" and slot: "Tuesday at 14:30". Those values come from your tool. The session events show which arguments the model chose and what the tool returned. A request that needs clarification may finish without a tool call.

const outcome = {
	status: run.status,
	state: { reference: run.state.reference, slot: run.state.slot },
	tools: run.session.events.filter((event) =>
		event.type === 'tool_call' || event.type === 'tool_result',
	),
	usage: run.usage,
}

outcome

You have a live agent, structured application state, and explicit model context. The Context guide shows how to select and filter history when several agents work in one session.

Keep building.