Documentation
Concepts

Tools

Flapjack agents can call tools during conversations: webhooks, MCP servers, database integrations, web tools, memory, and computer use.

Tools extend what an agent can do beyond generating text. During a conversation, the agent can decide to call tools, execute them, and incorporate the results into its response.

Tool Types

TypeDescriptionConfiguration
Webhook ToolsCustom HTTP endpoints the agent can callDashboard → Agent → Tools
MCP ServersExternal tool servers via Model Context ProtocolDashboard → MCP Servers
Database IntegrationsQuery Postgres/Supabase tables directlyDashboard → Integrations
Web ToolsSearch, research, read, and crawl the webDashboard → Agent → Web
MemoryStore and recall information across conversationsDashboard → Agent → Memory
Computer UseExecute code in sandboxed environmentsDashboard → Agent → Computer

Dashboard-configured tools (webhook, MCP, database, web, memory, computer) require no SDK-side setup. Custom tools are defined at runtime via the SDK.

How Tool Calling Works

User sends message
    → Agent receives message + tool definitions
    → Agent decides to call a tool
    → Flapjack executes the tool
    → Agent receives the result
    → Agent may call more tools (up to 10 per turn)
    → Agent generates final response

During streaming, tool activity produces these events:

  1. tool_call — the agent decided to call a tool (includes name and arguments)
  2. tool_executing — execution has started
  3. tool_result — execution completed with a result

Webhook Tools

Custom HTTP endpoints your agent can call. Define them in the dashboard with:

  • Name: What the agent sees (e.g., "get_weather")
  • Description: When to use it (the agent reads this)
  • URL: The endpoint to POST to
  • Parameters: JSON schema for the tool's input

When the agent calls a webhook tool, Flapjack POSTs the arguments to your endpoint with an HMAC signature for verification.

MCP Servers

Connect any Model Context Protocol server to give your agent access to external tools. Examples: GitHub, Slack, PostHog, Supabase.

  • Tools are discovered automatically via tools/list
  • Tool names are namespaced as {slug}__{tool_name} to avoid collisions
  • Supports HTTP, SSE, and stdio transports
  • OAuth 2.1 support for authenticated servers

MCP Guide

Database Integrations

Connect a Postgres or Supabase database and the agent gets auto-generated tools:

  • query_{table} — Run read queries against a table
  • count_{table} — Count rows matching conditions

The agent can query your data directly during conversations. Schema is introspected and cached automatically.

Postgres Integration Guide

Web Tools

Enable per-agent in the dashboard:

ToolWhat It Does
web_searchSearch the web (powered by Perplexity)
web_researchExtended research with multiple queries
web_readRead a specific URL (powered by Firecrawl)
web_crawlCrawl a website and extract content

Web Tools Guide

Memory

Agents with memory enabled can store and recall information across conversations:

  • Store: Save a fact or preference for later
  • Recall: Search stored memories by semantic similarity

Memory can be scoped to the agent (shared across all threads), a specific thread, or a resource.

Memory

Custom Tools (Client-Side)

You can define tools at runtime and execute them client-side. Pass tool definitions via the tools option in sendMessage, and handle calls with onToolCall:

const tools = [{
  name: 'get_weather',
  description: 'Get current weather for a city',
  parameters: {
    type: 'object',
    properties: { city: { type: 'string' } },
    required: ['city'],
  },
}];

for await (const event of client.sendMessage(threadId, 'What is the weather in London?', {
  tools,
  onToolCall: async (call) => {
    // Execute the tool and return the result
    const data = await fetchWeather(call.arguments);
    return JSON.stringify(data);
  },
})) {
  if (event.type === 'token') process.stdout.write(event.delta);
}

When the agent calls a custom tool, a requires_action event is emitted. If onToolCall is provided, results are submitted automatically and streaming continues. Without onToolCall, use client.submitToolResults() to resume the stream manually.

Tool definitions follow the OpenAI function calling schema format: name, description, and parameters (JSON Schema).

Showing Tool Activity in UI

When building a chat UI, display tool activity to users for transparency:

for await (const event of client.sendMessage(threadId, message)) {
  switch (event.type) {
    case 'token':
      appendToResponse(event.delta);
      break;
    case 'tool_call':
      showToolIndicator(`Using ${event.tool.name}...`);
      break;
    case 'tool_result':
      hideToolIndicator();
      break;
    case 'done':
      finalizeResponse(event.content);
      break;
  }
}
📋 Copy as prompt

Handle Flapjack streaming events to show tool activity in the UI. Display "Using {tool_name}..." when a tool_call event arrives, hide it on tool_result, and render token deltas as they stream.

Tool Profiles

Tool profiles let you define named subsets of tools on an agent, each with its own system prompt instructions. This enables mode-based interactions where the agent's capabilities change based on user intent.

Defining Profiles

Configure profiles on an agent via the API:

await client.updateAgent(agentId, {
  toolProfiles: {
    chat: {
      label: 'Chat',
      description: 'General Q&A and exploration',
      icon: '💬',
      tools: ['get_feature_tags', 'github_read_file', 'web_search'],
      systemPromptAppend: 'You are in Chat mode. Help the user explore.',
    },
    triage: {
      label: 'Triage',
      description: 'Review changes and manage features',
      icon: '📋',
      tools: ['get_feature_tags', 'suggest_feature_tag', 'create_feature_tag'],
      systemPromptAppend: 'You are in Triage mode. Help the user review changes.',
    },
  },
  defaultProfile: 'chat',
});

How It Works

  • Each profile specifies which tool names are visible to the LLM
  • Tools not listed in the active profile are excluded from the request
  • The profile's systemPromptAppend is appended to the agent's preamble
  • A built-in propose_profile_switch tool is auto-injected in all profiles

Profile Switching

The agent can call the propose_profile_switch tool to suggest changing modes. This emits a profile_switch_proposal SSE event. The client confirms the switch:

// In useChat options
onProfileSwitch: (proposal) => {
  if (confirm(`Switch to ${proposal.target}? ${proposal.reason}`)) {
    switchProfile(proposal.target);
  }
}

Per-Message Override

Override the active profile for a single message:

await client.sendMessage(threadId, 'Review this PR', {
  toolProfile: 'triage',
});

Thread Persistence

The active profile is stored on the thread. Set it at creation or update it later:

const thread = await client.createThread({ agentId, activeProfile: 'chat' });
await client.updateThread(threadId, { activeProfile: 'triage' });

Skills

Tool definitions, MCP server bindings, and prompt fragments can also be packaged as a Skill and reused across many agents. See Skills.

Next Steps

  • MCP: Overview — connect external tool servers
  • Skills — reusable bundles of prompts, tools, and MCP servers
  • Knowledge — RAG with document upload
  • Memory — persistent agent memory
Docs last updated May 11, 2026