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
| Type | Description | Configuration |
|---|---|---|
| Webhook Tools | Custom HTTP endpoints the agent can call | Dashboard → Agent → Tools |
| MCP Servers | External tool servers via Model Context Protocol | Dashboard → MCP Servers |
| Database Integrations | Query Postgres/Supabase tables directly | Dashboard → Integrations |
| Web Tools | Search, research, read, and crawl the web | Dashboard → Agent → Web |
| Memory | Store and recall information across conversations | Dashboard → Agent → Memory |
| Computer Use | Execute code in sandboxed environments | Dashboard → Agent → Computer |
| Scheduled Tasks | Schedule reminders and recurring agent jobs | Dashboard → Agent → Settings |
| Channel Adapters | Connect to Telegram, Slack, WhatsApp | Dashboard → 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:
tool_call— the agent decided to call a tool (includes name and arguments)tool_executing— execution has startedtool_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
Database Integrations
Connect a Postgres or Supabase database and the agent gets auto-generated tools:
query_{table}— Run read queries against a tablecount_{table}— Count rows matching conditions
The agent can query your data directly during conversations. Schema is introspected and cached automatically.
Web Tools
Enable per-agent in the dashboard:
| Tool | What It Does |
|---|---|
web_search | Search the web (powered by Perplexity) |
web_research | Extended research with multiple queries |
web_read | Read a specific URL (powered by Firecrawl) |
web_crawl | Crawl a website and extract content |
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
systemPromptAppendis appended to the agent's preamble - A built-in
propose_profile_switchtool 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:
| Tool | Description |
|---|---|
schedule_task | Create a one-shot or recurring task |
list_scheduled_tasks | List tasks for the current conversation |
cancel_scheduled_task | Cancel a task by ID |
Task Kinds
| Kind | Behavior |
|---|---|
reminder | Delivers a message back to the conversation at the scheduled time |
agent_turn | Runs 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: active → completed (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
| Platform | Credentials Required |
|---|---|
telegram | Bot token from @BotFather |
slack | Bot token + signing secret |
whatsapp | Bridge URL + API key (via WhatsApp Business bridge) |
Thread Strategies
| Strategy | Behavior |
|---|---|
persistent | One Flapjack thread per contact, forever. All messages continue the same conversation. |
session | New 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
| Endpoint | Description |
|---|---|
GET /api/agents/{agentId}/channels | List channels (includes contact counts) |
POST /api/agents/{agentId}/channels | Create 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}/contacts | List 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