Native Tools

Tools are Vercel AI SDK tool() definitions with Zod schemas for parameter validation. They are factory functions that accept a ToolContext and return the tool definition — this allows tools to be dynamically composed per-request based on the user's connected integrations.


Tool Context

Every tool receives this context:

interface ToolContext {
  userId: string;
  agentId: string;
  agentEmail?: string;
  integrations: {
    google?: string;   // decrypted OAuth access token
    notion?: string;
    slack?: string;
    github?: string;
  };
}

Tool Registry

buildToolset(ctx) in tools/index.ts composes the toolset dynamically:

  • Always available: knowledge_search, knowledge_store, manage_todos
  • If BRAVE_API_KEY set: web_search
  • If FIRECRAWL_API_KEY set: web_scrape
  • If agent has email + RESEND_API_KEY: send_email, read_inbox
  • If Google OAuth connected: read_emails, read_calendar, create_event
  • If Notion OAuth connected: notion_read, notion_write

This means an agent whose user hasn't connected Google won't see email/calendar tools at all — no "tool not available" errors, just clean scoping.


Tool Reference

knowledge_search

Search the user's personal knowledge base using Pinecone vector similarity.

Parameters: query (string), limit (number, default 5)

Backing: searchUserKnowledge() from knowledge.ts


knowledge_store

Save a new piece of knowledge about the user.

Parameters: content (string), type (fact/preference/knowledge/note), importance (0-1)

Backing: storeUserKnowledge() from knowledge.ts


manage_todos

List, create, complete, or update todos.

Parameters: action (list/create/complete/update), title, todoId, description, priority, dueDate

Backing: Direct Supabase CRUD on todos table


web_search

Search the web for information via Brave Search API.

Parameters: query (string)

Returns: Top 5 results with title, URL, and description


web_scrape

Extract content from any URL as markdown.

Parameters: url (string)

Backing: scrapeUrl() from scraper.ts via Firecrawl API


send_email

Send an email on the agent's behalf via Mailgun.

Parameters: to (email), subject (string), body (string)

Backing: sendAgentEmail() from agent-mail.ts


read_emails

Read the user's Gmail inbox.

Parameters: query (Gmail search query, optional), maxResults (number, max 10)

Backing: Gmail API with automatic OAuth token refresh


read_calendar

Read upcoming events from Google Calendar.

Parameters: days (number, default 7)

Backing: Google Calendar API


create_event

Create a new Google Calendar event.

Parameters: summary, startTime (ISO), endTime (ISO), description, location

Backing: Google Calendar API


notion_read

List available Notion pages or read a specific page's content.

Parameters: action (list/read), pageId, query

Backing: listAccessiblePages(), readNotionPage() from notion.ts


notion_write

Create a new page or append content to an existing page in Notion.

Parameters: action (create/append), title, parentPageId, pageId, content

Backing: createNotionPage(), appendToNotionPage() from notion.ts


browser_navigate

Navigate to a URL in the browser. Returns the page content. Use this for JavaScript-rendered pages, dashboards, or any site that needs a real browser.

Parameters: url (string)

Backing: Stagehand + Browserbase cloud browser. Sessions persist so agents keep login state.


browser_act

Perform an action in the browser using natural language — click buttons, fill forms, scroll, select options. Stagehand translates natural language into DOM interactions.

Parameters: action (string — e.g. "click the Sign In button", "type hello@example.com into the email field")

Backing: stagehand.act() — AI-native DOM interaction


browser_extract

Extract specific information from the current browser page using natural language.

Parameters: instruction (string — e.g. "get the product name and price", "list all meeting times")

Backing: stagehand.extract() — AI-powered data extraction


browser_observe

Observe the current page — see what elements are visible and what actions are possible. Use this to understand a page before acting on it.

Parameters: instruction (string, optional)

Backing: stagehand.observe() — returns list of interactive elements


Adding New Tools

  1. Create a new file in web/lib/agent-runtime/tools/ (e.g. slack.ts)
  2. Export a factory function that takes ToolContext and returns a tool() definition
  3. Register it in tools/index.ts inside buildToolset() with the appropriate condition
  4. The tool will automatically appear in agents' available tools when the condition is met