Theo Docs
TheoKitTheoKit-SDKTheoUITheo PaaS
Getting started

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:

  1. Uses a typed getWeather tool with Zod schema validation.
  2. Persists conversations so the user can come back later.
  3. Optionally enables long-term memory.

Prerequisites

  • Quickstart done — you have @theokit/sdk installed and an OPENROUTER_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:

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:

  • defineTool is the canonical tool factory. The Zod schema is converted to JSON Schema automatically at runtime.
  • execute is type-checked against the schema — city is typed as string.
  • 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:

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:

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.ts

Expected 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:

src/resume.ts
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 tool

The 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

On this page