Documentation
Concepts

Tools

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

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
Scheduled TasksSchedule reminders and recurring agent jobsDashboard → Agent → Settings
Channel AdaptersConnect to Telegram, Slack, WhatsAppDashboard → Agent → Channels

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' });

Scheduled Tasks

Agents with scheduled tasks enabled can schedule reminders and recurring jobs directly from a conversation. Enable via the dashboard under Agent → Settings → Scheduled Tasks, or via the API:

curl -X PUT https://api.flapjack.dev/api/agents/{agentId}/scheduled-tasks \
  -H "Authorization: Bearer fj_live_..." \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'

When enabled, the agent receives three built-in tools:

ToolDescription
schedule_taskCreate a one-shot or recurring task
list_scheduled_tasksList tasks for the current conversation
cancel_scheduled_taskCancel a task by ID

Task Kinds

KindBehavior
reminderDelivers a message back to the conversation at the scheduled time
agent_turnRuns a full agent turn with tools at the scheduled time — useful for reports, summaries, and lookups

Scheduling Syntax

The execute_at parameter accepts ISO 8601 timestamps or relative shorthands:

  • "30m" — 30 minutes from now
  • "2h" — 2 hours from now
  • "1d" — 1 day from now
  • "2026-07-01T09:00:00Z" — absolute timestamp

For recurring tasks, pass a cron expression in the recurrence field (e.g. "0 9 * * *" for daily at 9 AM). Omit for one-shot tasks.

Lifecycle

Tasks move through these statuses: activecompleted (one-shot after firing), paused, or cancelled. One-shot tasks have max_fires set to 1 and complete after a single execution. Recurring tasks default to unlimited fires and stay active until explicitly cancelled or paused. A task that fails 5 consecutive times is auto-cancelled.

Channel Adapters

Channel adapters connect an agent to messaging platforms so users can interact with it via Telegram, Slack, WhatsApp, or other channels. Each adapter translates platform-specific messages into Flapjack threads and streams responses back.

Configure channels in the dashboard under Agent → Channels, or via the API:

curl -X POST https://api.flapjack.dev/api/agents/{agentId}/channels \
  -H "Authorization: Bearer fj_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "telegram",
    "credentials": {"bot_token": "123456:ABC-DEF..."},
    "thread_strategy": "session",
    "session_timeout_min": 30
  }'

Supported Platforms

PlatformCredentials Required
telegramBot token from @BotFather
slackBot token + signing secret
whatsappBridge URL + API key (via WhatsApp Business bridge)

Thread Strategies

StrategyBehavior
persistentOne Flapjack thread per contact, forever. All messages continue the same conversation.
sessionNew thread created after session_timeout_min minutes of inactivity (default: 30).

How It Works

Platform (Telegram/Slack/WhatsApp)
    → Webhook POST /api/channels/{platform}/webhook?token={webhook_secret}
    → Resolve contact (create or match existing)
    → Resolve thread (per thread_strategy)
    → Run agent turn (same as SDK/API)
    → Stream response back to platform

Inbound messages are verified using the channel's webhook secret. The adapter handles message formatting, chunking (platforms have per-message length limits), and typing indicators.

Channel Management Endpoints

EndpointDescription
GET /api/agents/{agentId}/channelsList channels (includes contact counts)
POST /api/agents/{agentId}/channelsCreate channel + register webhook
PATCH /api/agents/{agentId}/channels/{channelId}Update config, strategy, or credentials
DELETE /api/agents/{agentId}/channels/{channelId}Delete channel + unregister webhook
GET /api/agents/{agentId}/channels/{channelId}/contactsList contacts for a channel

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 June 29, 2026