Your first agent
A 15-minute tutorial — build a weather-bot with a typed tool, conversation persistence, and optional memory.
This tutorial takes ~15 minutes. By the end you'll have an agent that:
- Uses a typed
getWeathertool with Zod schema validation. - Persists conversations so the user can come back later.
- Optionally enables long-term memory.
Prerequisites
- Quickstart done — you have
@theokit/sdkinstalled and anOPENROUTER_API_KEY(or any provider key) set. - You're in a fresh project directory with a
package.json.
Step 1 — Define a typed tool
Create src/tools.ts:
import { defineTool } from "@theokit/sdk";
import { z } from "zod";
export const getWeather = defineTool({
name: "get_weather",
description: "Look up the current weather in a given city.",
inputSchema: z.object({
city: z.string().describe("City name, e.g. 'Brasília' or 'Tokyo'."),
}),
async execute({ city }) {
// In a real app, hit a weather API. For the tutorial, we mock.
const mock: Record<string, string> = {
"Brasília": "27°C, sunny",
"Tokyo": "18°C, cloudy",
"London": "12°C, raining",
};
return mock[city] ?? `No weather data for ${city}.`;
},
});Notes:
defineToolis the canonical tool factory. The Zod schema is converted to JSON Schema automatically at runtime.executeis type-checked against the schema —cityis typed asstring.- The agent decides when to call this tool based on the user's prompt and the tool description.
Step 2 — Wire the tool into an Agent
Create src/agent.ts:
import { Agent } from "@theokit/sdk";
import { getWeather } from "./tools.js";
export async function makeAgent() {
return Agent.create({
apiKey: process.env.OPENROUTER_API_KEY,
model: { id: "openai/gpt-4o-mini" },
name: "weather-bot",
systemPrompt:
"You are a concise weather assistant. Use the get_weather tool when the user asks about weather.",
tools: [getWeather],
});
}Step 3 — Run it
Create src/run.ts:
import { makeAgent } from "./agent.js";
const agent = await makeAgent();
const run = await agent.send("What's the weather in Brasília?");
const result = await run.wait();
console.log(result.result);
await agent.dispose();Execute:
npx tsx src/run.tsExpected output:
The weather in Brasília is 27°C, sunny.You can verify the tool was actually called by inspecting result.messages — there'll be a tool_use block before the assistant's final reply.
Step 4 — Persist the conversation
So far, every Agent.create() gets a fresh context. To resume an existing conversation:
import { Agent } from "@theokit/sdk";
import { getWeather } from "./tools.js";
// First time: create + remember the id
const agent = await Agent.create({
apiKey: process.env.OPENROUTER_API_KEY,
model: { id: "openai/gpt-4o-mini" },
name: "weather-bot",
tools: [getWeather],
});
console.log("Agent ID:", agent.agentId);
await (await agent.send("What's the weather in Tokyo?")).wait();
await agent.dispose();
// Later (or in a different process): resume from the same id
const resumed = await Agent.resume(agent.agentId);
const run = await resumed.send("And in Brasília?"); // remembers Tokyo
const result = await run.wait();
console.log(result.result);
await resumed.dispose();Agent.resume(id) rehydrates the full message history + tool registry from disk (default: .theokit/agents/<id>/).
Step 5 (optional) — Add long-term memory
Persistence remembers the current session. Long-term memory lets the agent recall facts across sessions.
const agent = await Agent.create({
apiKey: process.env.OPENROUTER_API_KEY,
model: { id: "openai/gpt-4o-mini" },
tools: [getWeather],
memory: {
enabled: true,
// SDK provisions a SQLite + sqlite-vec store under .theokit/memory/
},
});
await (await agent.send("Remember that my home city is Brasília.")).wait();
// ... later, even in a fresh process after Agent.resume ...
const r = await (await agent.send("What's the weather here?")).wait();
console.log(r.result); // The agent recalls "home city = Brasília" + calls the toolThe enabled: true flag turns on Active Memory (recall before each send, store after each reply). The default backend is SQLite + sqlite-vec — zero setup.
What's next
Concepts: Agent
Deeper dive into lifecycle, options, LocalAgent vs CloudAgent, and persistence internals.
Concepts: Tools
Tool patterns: error handling, async, MCP tools, dynamic tool dispatch.
Concepts: Memory
FTS5 + sqlite-vec, LanceDB backend, embedding providers, custom adapters.
Cookbook
Runnable recipes for handoffs, workflows, semantic cache, and gateways.