Agent Runtime
The runtime lives at web/lib/agent-runtime/ and handles everything from model selection to tool execution.
File Structure
web/lib/agent-runtime/
index.ts — Public barrel exports
providers.ts — Model-agnostic provider resolution
prompt-builder.ts — System prompt construction
chat-loop.ts — Streaming + non-streaming chat loops
tools/
index.ts — Tool registry (buildToolset)
types.ts — Shared ToolContext interface
web-search.ts — Brave Search API
web-scrape.ts — Firecrawl URL extraction
send-email.ts — Resend email sending
read-inbox.ts — Agent inbox reading
read-emails.ts — Gmail API via OAuth
calendar.ts — Google Calendar read + create
notion.ts — Notion read + write
knowledge.ts — Pinecone RAG search + store
manage-todos.ts — Supabase todo CRUD
Chat Loop
The chat loop uses the Vercel AI SDK's streamText() and generateText() functions which handle the tool-use loop automatically.
Streaming (1:1 chat)
Used by /api/agents/[id]/chat for real-time agent conversations:
const result = streamText({
model,
system: systemPrompt,
messages,
tools,
stopWhen: stepCountIs(10), // max 10 tool-use rounds
});
return result.toTextStreamResponse();
The SDK calls the LLM, if it returns tool calls, executes them via the execute functions defined on each tool, feeds results back, and repeats up to the step limit.
Non-streaming (background tasks)
Used for group chat responses, head agent coordination, Telegram replies:
const result = await generateText({
model,
system: systemPrompt,
messages,
tools,
stopWhen: stepCountIs(5),
});
return result.text;
Prompt Builder
buildSystemPrompt() replaces the old container-oriented buildSoulMd(). It constructs the system prompt from:
- Agent identity — Name, type, tone, verbosity, tagline
- Objective & instructions — Custom agent configuration
- Trust tier rules — Observer, Helper, Partner, or Trusted
- Available tools — Dynamically listed based on what's registered
- User context — Name, occupation, goals, interests from personalization
- Knowledge context — RAG results from Pinecone
- Training data — Custom knowledge, instructions, and examples
- Group chat context — Team roster and skip guidance (for home chat)
Usage Tracking
Every LLM call logs token usage to the usage_logs table via trackUsage():
- Input tokens
- Output tokens
- Model name and provider
- Cost in cents (calculated from pricing tables)
- Operation type (
chat,checkin,embedding, etc.)
This enables per-agent, per-user cost visibility.
Key API Routes
| Route | Method | Transport | Purpose |
|-------|--------|-----------|---------|
| /api/agents/[id]/chat | POST | Streaming | 1:1 agent chat |
| /api/home/chat | POST | Non-streaming | Group chat responses |
| /api/agents/[id]/greet | POST | Non-streaming | Thread greeting |
| /api/home/head-agent | POST | Non-streaming | Head agent coordination |
| /api/integrations/telegram/webhook/[agentId] | POST | Non-streaming | Telegram bot messages |