# A2A Protocol Source: https://docs.crewform.tech/a2a-protocol Agent-to-Agent interoperability — expose CrewForm agents to external AI systems and delegate tasks to remote agents ## Overview CrewForm supports the **A2A (Agent-to-Agent) protocol**, enabling your agents to communicate with external AI systems. This is the open standard for agent-to-agent interoperability. A2A complements MCP (tools) and AG-UI (frontend) — together they form the **three agentic protocols** that CrewForm supports. ## How It Works A2A provides two capabilities: ### A2A Server — Expose Your Agents External platforms can discover and call your CrewForm agents via standard A2A endpoints: | Endpoint | Method | Description | | ------------------------- | ------ | ----------------------------------------------------------------------- | | `/.well-known/agent.json` | GET | Agent Card discovery — returns agent capabilities, skills, and metadata | | `/a2a/:agentId` | POST | JSON-RPC endpoint — accepts `message/send`, `tasks/get`, `tasks/cancel` | **Agent Card example:** ```json theme={null} { "name": "Research Agent", "description": "Performs web research and summarization", "version": "1.0.0", "skills": [ { "id": "web_research", "name": "Web Research", "description": "Search the web and compile findings" } ] } ``` ### A2A Client — Delegate to External Agents CrewForm agents can delegate tasks to any external A2A-compliant agent using the built-in `a2a_delegate` tool. **How to enable:** 1. Go to **Settings → A2A Protocol** 2. Enter the base URL of the external agent (e.g. `https://agent.example.com`) 3. Click **Discover** — CrewForm fetches the Agent Card and registers the agent 4. Toggle the agent to **Enabled** 5. Add `a2a_delegate` to any agent's tool list The agent can then call: ``` a2a_delegate(agent_id: "remote-agent-uuid", message: "Research the latest AI trends") ``` ## Authentication A2A endpoints require a **Bearer token** matching an API key in your workspace: ```bash theme={null} curl -X POST https://your-task-runner/a2a/AGENT_ID \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"message/send","params":{"message":{"role":"user","parts":[{"text":"Hello"}]}},"id":"1"}' ``` ## Managing Remote Agents Navigate to **Settings → A2A Protocol** to: * **Discover** — Register external agents by URL * **Toggle** — Enable/disable remote agents * **Refresh** — Update cached Agent Cards * **Delete** — Remove remote agent registrations ## Database A2A uses two tables: * `a2a_remote_agents` — Registered external agents and cached Agent Cards * `a2a_task_log` — Inbound and outbound A2A interaction history # AG-UI Protocol Source: https://docs.crewform.tech/ag-ui-protocol Real-time SSE streaming for frontend integration — the open standard for agent-to-UI communication ## Overview CrewForm supports the **AG-UI (Agent-User Interaction) protocol**, enabling real-time streaming of agent execution events to any compatible frontend via Server-Sent Events (SSE). AG-UI complements MCP (tools) and A2A (agents) — together they form the **three agentic protocols** that CrewForm supports. ## How It Works When a CrewForm agent executes a task, the task runner emits structured AG-UI events through an SSE endpoint. Any frontend — CrewForm's dashboard, a custom app, or a CopilotKit integration — can subscribe and display execution in real-time. ``` Agent Executor → AG-UI Event Bus → SSE Endpoint → Your Frontend ``` ### Event Types | Event | Description | | ---------------------- | ------------------------------------------ | | `RUN_STARTED` | Task execution begins | | `TEXT_MESSAGE_START` | LLM response stream begins | | `TEXT_MESSAGE_CONTENT` | LLM response token chunk | | `TEXT_MESSAGE_END` | LLM response stream ends | | `TOOL_CALL_START` | Tool execution begins (includes tool name) | | `TOOL_CALL_ARGS` | Tool call arguments | | `TOOL_CALL_END` | Tool execution completes (includes result) | | `RUN_FINISHED` | Task completes successfully | | `RUN_ERROR` | Task fails with error message | | `INTERACTION_REQUEST` | Agent pauses and requests user input | | `INTERACTION_RESPONSE` | User submitted their response | | `INTERACTION_TIMEOUT` | Interaction timed out without response | ## Rich Interactions AG-UI supports **bidirectional communication** — agents can pause execution, present choices to the user, and resume based on user input. ### Interaction Types | Type | When to use | User sees | | -------------- | ------------------------------------------- | --------------------------------------- | | `approval` | Agent needs permission before proceeding | Approve / Reject buttons | | `confirm_data` | Agent wants the user to verify or edit data | Data table with Confirm / Edit / Reject | | `choice` | Agent needs the user to pick from options | Radio button list with Select | ### How It Works ``` Agent executes → INTERACTION_REQUEST → Agent pauses ↓ User sees modal, makes decision ↓ POST /respond → INTERACTION_RESPONSE → Agent resumes ``` ### INTERACTION\_REQUEST Event When an agent requests input, the SSE stream emits: ```json theme={null} { "type": "INTERACTION_REQUEST", "timestamp": 1711000010, "threadId": "task-uuid", "interactionId": "uuid", "interactionType": "approval", "title": "Deploy to production?", "description": "The agent wants to deploy version 2.4.1 to production.", "timeoutMs": 300000 } ``` For `confirm_data`, includes a `data` object. For `choice`, includes a `choices` array. ### Submitting a Response ``` POST /ag-ui/:agentId/respond ``` **Body:** ```json theme={null} { "threadId": "task-uuid", "interactionId": "uuid", "approved": true } ``` For `confirm_data`, include `data` with modified values. For `choice`, include `selectedOptionId`. ### React Hook Usage The `useAgentStream` hook handles interactions automatically: ```typescript theme={null} const { status, textContent, pendingInteraction, respond } = useAgentStream( 'https://your-task-runner-url', agentId, taskId, apiKey, true ) // When an interaction is pending, show the modal if (pendingInteraction) { return ( ) } ``` ### Timeout Behavior * Default timeout: **5 minutes** per interaction * When the timeout expires, the agent emits `INTERACTION_TIMEOUT` and the task fails * The task status transitions: `running` → `waiting_for_input` → `failed` * Timeout duration is included in the `INTERACTION_REQUEST` event ## Authentication AG-UI uses the same Bearer token auth as A2A — provide an API key from your workspace's `api_keys` table (provider: `ag-ui` or `a2a`). ## Important Notes * The SSE stream is **real-time only** — connect before or during task execution * Events stream for the duration of task execution and close on completion * The `threadId` maps to a CrewForm task ID * Works with any AG-UI-compatible client, including CopilotKit * Rich interactions require a connected SSE client to display the modal — if no client is connected, the interaction will time out ### Request ``` POST /ag-ui/:agentId/sse ``` **Headers:** ``` Content-Type: application/json Authorization: Bearer YOUR_API_KEY ``` **Body** (RunAgentInput): ```json theme={null} { "threadId": "task-uuid", "runId": "task-uuid" } ``` ### Response The endpoint returns `text/event-stream` with AG-UI events: ``` data: {"type":"RUN_STARTED","timestamp":1711000000,"threadId":"abc","runId":"abc"} data: {"type":"TEXT_MESSAGE_START","timestamp":1711000001,"messageId":"msg_1","role":"assistant"} data: {"type":"TEXT_MESSAGE_CONTENT","timestamp":1711000002,"messageId":"msg_1","delta":"Here is "} data: {"type":"TEXT_MESSAGE_CONTENT","timestamp":1711000003,"messageId":"msg_1","delta":"the result..."} data: {"type":"TEXT_MESSAGE_END","timestamp":1711000004,"messageId":"msg_1"} data: {"type":"RUN_FINISHED","timestamp":1711000005,"threadId":"abc","runId":"abc","result":"Here is the result..."} ``` ## Quick Test ### Health Check ```bash theme={null} curl http://localhost:3001/ag-ui/health # → {"status":"ok","protocol":"ag-ui","version":"1.1"} ``` ### Stream Events ```bash theme={null} # In terminal 1: Connect to SSE stream curl -N -X POST http://localhost:3001/ag-ui/AGENT_ID/sse \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{"threadId":"TASK_ID","runId":"TASK_ID"}' # In terminal 2: Trigger the task via API or dashboard ``` ## React Hook CrewForm includes a `useAgentStream` React hook for consuming AG-UI events: ```typescript theme={null} import { useAgentStream } from '@/hooks/useAgentStream' function TaskStreamView({ taskId, agentId, apiKey }) { const { status, textContent, toolCalls, error } = useAgentStream( 'https://your-task-runner-url', agentId, taskId, apiKey, true // enabled ) return (

Status: {status}

{textContent}
{toolCalls.map(tc => (
🔧 {tc.name}: {tc.status === 'done' ? tc.result : 'running...'}
))}
) } ``` ### Hook Return Values | Field | Type | Description | | -------------------- | ----------------------------------------------------------------- | ------------------------------------------ | | `status` | `'idle' \| 'connecting' \| 'streaming' \| 'completed' \| 'error'` | Connection state | | `textContent` | `string` | Accumulated LLM response text | | `toolCalls` | `AgUiToolCall[]` | Tool calls with name, args, result, status | | `pendingInteraction` | `AgUiInteractionRequest \| null` | Current interaction awaiting user response | | `events` | `AgUiEvent[]` | All raw AG-UI events received | | `error` | `string \| null` | Error message if status is `'error'` | | `respond` | `(response) => Promise` | Submit a response to a pending interaction | # Agents Source: https://docs.crewform.tech/agents # Agents Guide Agents are the core building blocks of CrewForm. Each agent is an AI worker configured with a specific model, system prompt, and capabilities. ## Creating an Agent Navigate to **Agents → New Agent** or use the `+` button. ### Required Fields | Field | Description | | ----------------- | ------------------------------------------------------------ | | **Name** | Human-readable identifier (e.g., "Code Reviewer") | | **Model** | LLM model to use (see [Supported Models](#supported-models)) | | **System Prompt** | Instructions that define the agent's behavior | ### Optional Fields | Field | Description | | --------------- | ------------------------------------------------------ | | **Description** | What the agent does (shown in marketplace) | | **Temperature** | Creativity level (0.0 = deterministic, 1.0 = creative) | | **Max Tokens** | Maximum response length | | **Tags** | Categorization for search and marketplace | ## Supported Models CrewForm supports three LLM providers. You must add your API key in **Settings → API Keys** before using a provider. ### Anthropic (Claude) | Model | Best For | | --------------------------- | -------------------------------------- | | `claude-sonnet-4-20250514` | General-purpose, balanced cost/quality | | `claude-3-5-haiku-20241022` | Fast, cost-effective tasks | | `claude-3-opus-20240229` | Complex reasoning, analysis | ### Google (Gemini) | Model | Best For | | ------------------ | --------------------------- | | `gemini-2.0-flash` | Fast, multimodal tasks | | `gemini-1.5-pro` | Long-context, complex tasks | ### OpenAI (GPT) | Model | Best For | | --------------- | ------------------------- | | `gpt-4o` | General-purpose, fast | | `gpt-4-turbo` | Complex reasoning | | `gpt-3.5-turbo` | Simple, high-volume tasks | ## Writing System Prompts The system prompt defines your agent's personality, expertise, and output format. Tips: ### Be Specific ``` ❌ "You are a helpful assistant." ✅ "You are a senior code reviewer specializing in TypeScript and React. You review code for bugs, performance issues, and best practices. Output your review as a numbered list with severity (HIGH/MEDIUM/LOW)." ``` ### Define Output Format ``` You must respond in the following JSON format: { "summary": "one-line summary", "findings": [{ "severity": "HIGH|MEDIUM|LOW", "description": "..." }], "recommendation": "overall recommendation" } ``` ### Set Boundaries ``` You ONLY review code. If asked to write new code, respond with: "I'm configured as a reviewer. Please create a separate coding agent." ``` ## Agent Lifecycle ``` Created → Idle → Running (task assigned) → Idle ↓ Failed (error) ``` * **Idle**: Ready to accept tasks * **Running**: Actively processing a task * **Failed**: Task errored — check the task detail for the error message ## Output Routes By default, when an agent completes a task, the result is broadcast to **all** active output routes (HTTP webhooks, Slack, Discord, Telegram, Teams, Asana, Trello) in your workspace. See the [Output Routes guide](./output-routes.md) for how to configure destinations. You can restrict an agent to deliver results to specific channels only: 1. Open the agent in **Agents → \[Agent Name] → Settings** 2. Scroll to **Output Routes** 3. Select one or more channels from the dropdown — or leave blank to send to all > **Leave blank (default)** = broadcast to all active routes. Select specific channels to narrow delivery. This is useful when you have multiple output routes (e.g., a `#dev-alerts` Slack channel and a Telegram group) and only want certain agents to send to specific ones. ### How it works Under the hood, the agent stores a list of route UUIDs in `output_route_ids`: | Value | Behaviour | | ------------------ | -------------------------------------- | | `null` (default) | Dispatch to all active output routes | | `[]` (empty array) | Dispatch to no routes | | `[uuid, ...]` | Dispatch to only those specific routes | ## Voice Profiles Voice profiles let you control how an agent communicates — its tone, style, and formatting preferences. When a voice profile is configured, it's injected into the system prompt as a `## Voice & Tone` section before each execution. ### Configuring a Voice Profile 1. Open an agent → click the **Voice Profile** tab 2. Select a **Tone Preset** — Formal, Casual, Technical, Creative, Empathetic, or Custom 3. Add **Custom Voice Instructions** — e.g. *"Always refer to customers as 'members'. Use active voice. Avoid jargon."* 4. Add **Output Format Hints** (optional) — e.g. *"Use numbered lists for steps. Keep responses under 200 words."* 5. Click **Save Voice Profile** ### Tone Presets | Preset | Style | | -------------- | --------------------------------------- | | **Formal** | Professional, structured, precise | | **Casual** | Friendly, conversational, approachable | | **Technical** | Detailed, accurate, documentation-style | | **Creative** | Expressive, engaging, vivid language | | **Empathetic** | Warm, supportive, understanding | | **Custom** | Define your own tone | ### Brand Voice Templates You can save a voice profile as a reusable **Brand Voice Template** that other agents can share: 1. Configure the tone, instructions, and format hints 2. Click **Save as Template** → give it a name (e.g. "Acme Brand Voice") 3. On any other agent, select the template from the **Brand Voice Template** dropdown This ensures all customer-facing agents (or all internal agents) use the same voice consistently. ### How It Works at Runtime When the agent runs a task, the system prompt is constructed as: ``` [Agent's base system prompt] ## Voice & Tone Tone: formal Always refer to customers as 'members'. Use active voice. Avoid jargon. Output format: Use numbered lists for steps. Keep responses under 200 words. [Task instructions] ``` Voice profiles work across **all execution modes** — standalone tasks, pipeline steps, orchestrator delegations, and collaboration discussions. ## Output Templates Output templates let you format agent output consistently using `{{variable}}` placeholders. Instead of raw LLM text, results are wrapped in a structured template. ### Configuring an Output Template 1. Open an agent → click the **Output Template** tab 2. Select a **Template Type** — Markdown, JSON, HTML, CSV, or Custom 3. Write the **Template Body** using `{{variable}}` syntax: ```markdown theme={null} # {{task_title}} > Generated by **{{agent_name}}** on {{timestamp}} {{task_result}} --- *Tokens used: {{tokens_used}} · Model: {{model}}* ``` 4. Click **Preview** to see it rendered with sample data 5. Click **Save Template** ### Available Variables | Variable | Description | | ----------------- | ----------------------------------- | | `{{task_title}}` | Title of the task | | `{{task_result}}` | Full output from the agent | | `{{agent_name}}` | Name of the agent that ran the task | | `{{timestamp}}` | ISO 8601 timestamp of completion | | `{{tokens_used}}` | Total tokens used during execution | | `{{model}}` | Model ID used for execution | ### How It Works at Runtime After the LLM generates its response, the output template is applied: ``` LLM raw output → {{task_result}} slot in template → Final formatted result ``` Missing variables are left as `{{variable_name}}` in the output, so templates degrade gracefully. ## MCP Server Publishing You can expose any agent as an **MCP tool** that Claude Desktop, Cursor, or any MCP-compatible client can call directly. ### Publishing an Agent 1. Open the agent in **Agents → \[Agent Name]** 2. Click the **MCP Publish** button in the header bar 3. The button changes to **MCP Published** (green) — the agent is now exposed as an MCP tool Click again to unpublish. The agent immediately appears/disappears from the MCP tool list. ### What Happens When published, the agent becomes callable via the MCP protocol: | Property | Value | | --------------- | ----------------------------------------------------------------------------------------------------------------- | | **Tool Name** | Lowercase agent name, alphanumeric + underscores (e.g., "Code Reviewer" → `code_reviewer`) | | **Description** | Agent's description field | | **Input** | A `message` string — the prompt or task to send | | **Execution** | Full agent execution — same model, system prompt, tools, knowledge base, and voice profile as running from the UI | ### Connecting External Clients 1. Go to **Settings → MCP Servers** 2. Click **Generate MCP API Key** to create a `cf_mcp_` prefixed key 3. Copy the auto-generated config snippet into your client: ```json theme={null} { "mcpServers": { "crewform": { "url": "https://runner.crewform.tech/mcp", "headers": { "Authorization": "Bearer cf_mcp_your_key_here" } } } } ``` Each API key is scoped to a single workspace — only that workspace's published agents are visible. See the full [MCP Server Publishing Guide](./mcp-server-publishing.md) for detailed setup instructions. ## Export & Import ### Exporting an Agent 1. Open the agent in **Agents → \[Agent Name]** 2. Click the **Export** button in the header bar 3. A `crewform-agent-{name}.json` file downloads automatically The export includes: model, system prompt, temperature, max tokens, tags, tools, voice profile, and config. It does **not** include workspace-specific data like API keys, task history, or custom tools. ### Importing an Agent 1. Navigate to **Agents** list page 2. Click the **Import** button in the top-right 3. Select a `.json` file (CrewForm export format) 4. The agent is created with an `(imported)` suffix Importing a team export file from the Agents page will import the team **and** all its member agents. ### Export Format Exports use a versioned `crewform-export` format (v1) for forward compatibility: ```json theme={null} { "format": "crewform-export", "version": 1, "type": "agent", "exported_at": "2026-04-08T12:00:00.000Z", "data": { "name": "Code Reviewer", "model": "claude-sonnet-4-20250514", "system_prompt": "You are an expert code reviewer...", "tools": ["web_search", "knowledge_search"], ... } } ``` ## Using Agents in Teams Agents become more powerful when combined into teams. See the [Pipeline Teams Guide](./pipeline-teams.md) for multi-agent workflows. ## API Key Security All API keys are encrypted with **AES-256-GCM** before storage. Keys are: * Encrypted client-side before being sent to the database * Never stored in plaintext * Only decrypted by the task runner at execution time * Scoped to your workspace via Row-Level Security See \[Settings → API Keys] in the app to manage your provider keys. # Api reference Source: https://docs.crewform.tech/api-reference # REST API Reference CrewForm provides two API layers: * **[API v2](#api-v2-recommended)** — Edge Functions API with versioned envelopes, rate limiting, and pagination *(recommended)* * **[API v1 (Legacy)](#api-v1-legacy)** — Direct Supabase PostgREST access *(still supported)* *** # API v2 (Recommended) > **Base URL:** `https://.supabase.co/functions/v1` The v2 API uses CrewForm Edge Functions with structured responses, per-tier rate limiting, and cursor-based pagination. ## Authentication All requests require one of: | Method | Header | Use case | | ----------- | ------------------------------- | ---------------------------------- | | **API Key** | `X-API-Key: cf_your_key` | Zapier, scripts, third-party tools | | **JWT** | `Authorization: Bearer ` | Frontend, authenticated clients | Generate API keys in **Settings → API Keys**. ## Versioning Set `X-API-Version: 2` to opt into v2 response format. Omitting the header defaults to v1 (raw data, no envelope). ```bash theme={null} curl -H "X-API-Key: cf_..." \ -H "X-API-Version: 2" \ https://your-project.supabase.co/functions/v1/api-agents ``` ## Response Format **v2 Success:** ```json theme={null} { "data": { ... }, "meta": { "api_version": 2, "request_id": "req_abc123def456", "timestamp": "2026-03-13T10:00:00.000Z" } } ``` **v2 List (paginated):** ```json theme={null} { "data": { "items": [ ... ], "next_cursor": "2026-03-12T08:00:00.000Z", "has_more": true }, "meta": { ... } } ``` **v2 Error:** ```json theme={null} { "error": { "code": "not_found", "message": "Agent not found" }, "meta": { ... } } ``` ## Rate Limits Enforced per workspace per minute: | Plan | Requests/min | | ---------- | ------------ | | Free | 30 | | Pro | 120 | | Team | 300 | | Enterprise | 600 | Every response includes: ``` X-RateLimit-Limit: 120 X-RateLimit-Remaining: 117 X-RateLimit-Reset: 1710324360 ``` Exceeding the limit returns `429 Too Many Requests` with a `Retry-After` header. ## Pagination List endpoints support cursor-based pagination: | Param | Type | Default | Description | | -------- | ------ | ------- | ---------------------------------------------- | | `limit` | int | 50 | Items per page | | `cursor` | string | — | Cursor from `next_cursor` of previous response | ```bash theme={null} # First page curl -H "X-API-Key: cf_..." -H "X-API-Version: 2" \ "https://.../functions/v1/api-agents?limit=10" # Next page curl -H "X-API-Key: cf_..." -H "X-API-Version: 2" \ "https://.../functions/v1/api-agents?limit=10&cursor=2026-03-12T08:00:00.000Z" ``` *** ## Endpoints ### Agents — `/functions/v1/api-agents` | Method | Params | Description | | -------- | ------------------- | ---------------- | | `GET` | — | List all agents | | `GET` | `?id=` | Get single agent | | `POST` | body | Create agent | | `PATCH` | `?id=` + body | Update agent | | `DELETE` | `?id=` | Delete agent | **Create body:** ```json theme={null} { "name": "Code Reviewer", "model": "claude-sonnet-4-20250514", "description": "Reviews code for bugs and best practices", "system_prompt": "You are a senior code reviewer...", "temperature": 0.3, "tools": [], "status": "idle" } ``` ### Tasks — `/functions/v1/api-tasks` | Method | Params | Description | | -------- | ------------------- | ---------------------------------------------------- | | `GET` | — | List all tasks | | `GET` | `?status=running` | Filter by status | | `GET` | `?id=` | Get single task | | `POST` | body | Create task (auto-dispatches if agent/team assigned) | | `PATCH` | `?id=` + body | Update task | | `DELETE` | `?id=` | Delete task | **Create body:** ```json theme={null} { "title": "Review PR #42", "description": "Review the authentication changes", "priority": "high", "assigned_agent_id": "", "metadata": {} } ``` **Task statuses:** `pending`, `dispatched`, `running`, `waiting_for_input`, `completed`, `failed`, `cancelled` **Task priorities:** `low`, `medium`, `high`, `urgent` ### Teams — `/functions/v1/api-teams` | Method | Params | Description | | -------- | ------------------- | --------------------------------- | | `GET` | — | List all teams (includes members) | | `GET` | `?id=` | Get single team | | `POST` | body | Create team | | `PATCH` | `?id=` + body | Update team | | `DELETE` | `?id=` | Delete team | **Create body:** ```json theme={null} { "name": "Content Pipeline", "description": "Research → Write → Edit", "mode": "pipeline", "config": { "steps": [ { "agent_id": "", "step_name": "Research", "instructions": "Research the topic thoroughly", "expected_output": "Detailed research notes", "on_failure": "retry", "max_retries": 2 } ], "auto_handoff": true } } ``` **Team modes:** `pipeline`, `orchestrator`, `collaboration` ### Team Runs — `/functions/v1/api-runs` | Method | Params | Description | | ------ | ----------------- | ---------------------------------- | | `GET` | — | List all runs | | `GET` | `?team_id=` | Filter by team | | `GET` | `?id=` | Get single run (includes messages) | | `POST` | body | Start a new team run | **Create body:** ```json theme={null} { "team_id": "", "input_task": "Research the latest trends in AI agent frameworks" } ``` ### Webhook Hooks — `/functions/v1/api-hooks` | Method | Params | Description | | -------- | ------------ | --------------------------------- | | `GET` | — | List active webhook subscriptions | | `POST` | body | Subscribe (Zapier REST Hook) | | `DELETE` | `?id=` | Unsubscribe | **Subscribe body:** ```json theme={null} { "target_url": "https://hooks.zapier.com/...", "event": "task_completed" } ``` ### Identity — `/functions/v1/api-me` | Method | Description | | ------ | ------------------------------------------------------ | | `GET` | Returns current user, workspace, plan, and API version | **Response:** ```json theme={null} { "id": "", "email": "user@example.com", "name": "Vince", "workspace_id": "", "workspace_name": "My Workspace", "plan": "pro", "api_version": 2 } ``` *** ## Error Codes (v2) | Code | HTTP Status | Description | | --------------------- | ----------- | ---------------------------------- | | `bad_request` | 400 | Invalid request body or parameters | | `unauthorized` | 401 | Missing or invalid authentication | | `not_found` | 404 | Resource not found | | `method_not_allowed` | 405 | HTTP method not supported | | `rate_limit_exceeded` | 429 | Too many requests | | `internal_error` | 500 | Server error | *** ## Example: cURL ```bash theme={null} # List agents (v2 with envelope) curl -s \ -H "X-API-Key: cf_abc123..." \ -H "X-API-Version: 2" \ "https://your-project.supabase.co/functions/v1/api-agents" # Create a task and auto-dispatch to an agent curl -s -X POST \ -H "X-API-Key: cf_abc123..." \ -H "Content-Type: application/json" \ -d '{"title":"Review PR","description":"...","assigned_agent_id":""}' \ "https://your-project.supabase.co/functions/v1/api-tasks" # Start a team run curl -s -X POST \ -H "X-API-Key: cf_abc123..." \ -H "Content-Type: application/json" \ -d '{"team_id":"","input_task":"Research AI trends"}' \ "https://your-project.supabase.co/functions/v1/api-runs" ``` *** ### AG-UI Protocol — Task Runner Endpoints > **Base URL:** `https:///ag-ui` These endpoints are served by the task runner (not Edge Functions). They handle real-time agent streaming and user interactions. #### SSE Stream — `POST /ag-ui/:agentId/sse` Open an SSE connection to stream AG-UI events for a task execution. **Headers:** ``` Authorization: Bearer Content-Type: application/json ``` **Body:** ```json theme={null} { "threadId": "", "runId": "optional-run-id" } ``` **Response:** Server-Sent Events stream with AG-UI events: ``` data: {"type":"RUN_STARTED","timestamp":1711000000,"threadId":"..."} data: {"type":"TEXT_MESSAGE_CONTENT","timestamp":1711000001,"content":"Hello..."} data: {"type":"INTERACTION_REQUEST","interactionId":"uuid","interactionType":"approval",...} data: {"type":"RUN_FINISHED","timestamp":1711000010} ``` See [AG-UI Protocol](/ag-ui-protocol) for the full event type reference. #### Submit Interaction Response — `POST /ag-ui/:agentId/respond` Submit a user response to a pending interaction request. The task must be in `waiting_for_input` status. **Headers:** ``` Authorization: Bearer Content-Type: application/json ``` **Body (approval):** ```json theme={null} { "threadId": "", "interactionId": "", "approved": true } ``` **Body (data confirmation):** ```json theme={null} { "threadId": "", "interactionId": "", "approved": true, "data": { "name": "Corrected Name", "email": "updated@example.com" } } ``` **Body (choice):** ```json theme={null} { "threadId": "", "interactionId": "", "selectedOptionId": "option-2" } ``` **Success Response:** ```json theme={null} { "ok": true, "interactionId": "" } ``` **Error Responses:** | Status | Error | | ------ | --------------------------------------------- | | 400 | `threadId and interactionId are required` | | 401 | `Unauthorized — provide Bearer token` | | 404 | `Task not found` | | 409 | `Task is not waiting for input (status: ...)` | #### Health Check — `GET /ag-ui/health` ```json theme={null} { "status": "ok", "protocol": "ag-ui", "version": "1.1" } ``` *** *** # API v1 (Legacy) > **Base URL:** `https://.supabase.co/rest/v1` The v1 API provides direct Supabase PostgREST access. It is still supported but we recommend migrating to [API v2](#api-v2-recommended) for rate limiting, structured responses, and pagination. ## Authentication All API requests require a REST API key in the `Authorization` header: ```bash theme={null} curl -H "Authorization: Bearer crfm_your_api_key" \ -H "Content-Type: application/json" \ https://your-project.supabase.co/rest/v1/agents ``` ### Creating API Keys 1. Go to **Settings → API Keys** 2. Click **Generate Key** 3. Copy the key — it's only shown once 4. The key is hashed (SHA-256) before storage for security ## Endpoints All endpoints are accessed via the Supabase REST API at: ``` https://.supabase.co/rest/v1/ ``` You also need the `apikey` header with your Supabase anon key: ```bash theme={null} curl -H "Authorization: Bearer crfm_your_api_key" \ -H "apikey: your-supabase-anon-key" \ https://your-project.supabase.co/rest/v1/agents ``` *** ## Agents ### List Agents ```http theme={null} GET /rest/v1/agents?select=* ``` **Response:** ```json theme={null} [ { "id": "uuid", "name": "Code Reviewer", "description": "Reviews code for bugs and best practices", "model": "claude-sonnet-4-20250514", "provider": "anthropic", "system_prompt": "You are a senior code reviewer...", "temperature": 0.3, "max_tokens": 4096, "tags": ["code", "review"], "workspace_id": "uuid", "created_at": "2026-01-15T10:00:00Z", "updated_at": "2026-01-15T10:00:00Z" } ] ``` ### Create Agent ```http theme={null} POST /rest/v1/agents Content-Type: application/json { "name": "Code Reviewer", "model": "claude-sonnet-4-20250514", "provider": "anthropic", "system_prompt": "You are a senior code reviewer...", "workspace_id": "your-workspace-id" } ``` ### Update Agent ```http theme={null} PATCH /rest/v1/agents?id=eq.{agent_id} Content-Type: application/json { "name": "Updated Name", "temperature": 0.5 } ``` ### Delete Agent ```http theme={null} DELETE /rest/v1/agents?id=eq.{agent_id} ``` *** ## Tasks ### List Tasks ```http theme={null} GET /rest/v1/tasks?select=*&order=created_at.desc ``` **Query parameters for filtering:** | Parameter | Example | Description | | ---------- | ------------ | ------------------------ | | `status` | `eq.running` | Filter by status | | `priority` | `eq.high` | Filter by priority | | `agent_id` | `eq.{uuid}` | Filter by assigned agent | ### Create Task ```http theme={null} POST /rest/v1/tasks Content-Type: application/json { "title": "Review PR #42", "description": "Review the authentication changes", "agent_id": "uuid", "priority": "high", "workspace_id": "your-workspace-id" } ``` **Task statuses:** `pending`, `dispatched`, `running`, `waiting_for_input`, `completed`, `failed`, `cancelled` **Task priorities:** `low`, `medium`, `high`, `urgent` ### Get Task Detail ```http theme={null} GET /rest/v1/tasks?id=eq.{task_id}&select=* ``` *** ## Teams ### List Teams ```http theme={null} GET /rest/v1/teams?select=* ``` ### Create Team ```http theme={null} POST /rest/v1/teams Content-Type: application/json { "name": "Content Pipeline", "description": "Research → Write → Edit", "mode": "pipeline", "workspace_id": "your-workspace-id" } ``` ### Team Runs ```http theme={null} GET /rest/v1/team_runs?team_id=eq.{team_id}&select=*&order=created_at.desc ``` *** ## Usage Records ### Query Usage ```http theme={null} GET /rest/v1/usage_records?select=*&created_at=gte.2026-01-01&order=created_at.desc ``` **Response fields:** | Field | Type | Description | | -------------------- | ------- | ----------------------------------- | | `task_id` | uuid | Associated task | | `agent_id` | uuid | Agent that ran | | `provider` | string | LLM provider | | `model` | string | Model used | | `prompt_tokens` | integer | Input tokens | | `completion_tokens` | integer | Output tokens | | `estimated_cost_usd` | decimal | Estimated cost | | `billing_model` | string | `per-token` or `subscription-quota` | *** ## Marketplace ### Browse Agents ```http theme={null} GET /rest/v1/agents?is_marketplace=eq.true&select=* ``` ### Install Agent (RPC) ```http theme={null} POST /rest/v1/rpc/increment_install_count Content-Type: application/json { "agent_row_id": "uuid" } ``` *** ## Rate Limits (v1) The Supabase free tier includes: * **500 requests/minute** per API key * **50,000 requests/month** total For higher limits, upgrade your Supabase plan. ## Error Handling (v1) All errors follow the standard Supabase/PostgREST format: ```json theme={null} { "code": "PGRST301", "message": "Row not found", "details": null, "hint": null } ``` Common error codes: | HTTP Status | Meaning | | ----------- | -------------------------------- | | `401` | Missing or invalid API key | | `403` | Row-Level Security denied access | | `404` | Resource not found | | `409` | Conflict (duplicate key) | | `422` | Validation error | # Changelog Source: https://docs.crewform.tech/changelog All notable changes to CrewForm. # Changelog All notable changes to CrewForm will be documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## \[1.9.3] — 2026-05-14 ### Added * **CrewForm CLI (`npx crewform`)** — Standalone command-line tool for running AI agents locally without the web platform: * **12 Commands** — `run`, `chat`, `init`, `validate`, `tools`, `login`, `logout`, `whoami`, `agents`, `teams`, `pull`, `push` * **Local Agent Execution** — Run agents from JSON config files with streaming output, Ollama auto-detection, and 16 LLM provider support * **Pipeline Teams** — Multi-agent pipeline execution with sequential steps, fan-out (parallel branches), merge agents, and configurable failure handling * **MCP Client Integration** — Connect to MCP servers via `stdio`, `sse`, or `streamable-http` transports (`--mcp` flag) * **Interactive Chat** — REPL with conversation history, token/cost tracking, and `/clear`, `/history`, `/stats`, `/exit` commands * **Platform API Mode** — `crewform login` to authenticate, browse workspace agents/teams, `pull` configs locally, and `push` tasks remotely * **Config Compatibility** — Accepts inline JSON and full `crewform-export` v1 format from the web app * **Built-in Tools** — `web_search`, `http_request`, `code_interpreter`, `read_file`, `grammar_check` * **Zero-Config Start** — `crewform init` scaffolds agent or team configs with Ollama model auto-detection * **CI/CD Friendly** — `--json`, `--quiet`, stdin/stdout piping, and `CREWFORM_API_KEY` env var support ### Documentation * New [CLI Tool](/cli) guide added to docs ## \[1.9.2] — 2026-05-08 ### Added * **Google Workspace Gateway** — OAuth 2.0 integration with 4 output destinations: Google Sheets (row append), Gmail (send from your account), Google Docs (auto-create documents), Google Calendar (create review events) * **Notion Output Route** — Create pages in a Notion database with task results * **GitHub Issues Output Route** — Create issues with labels and assignees * **Email (Resend) Output Route** — Managed email delivery with HTML templates * **SMTP Email Output Route** — Self-hosted email via nodemailer * **Linear Output Route** — Create issues via GraphQL with team label resolution * **Serverless Cron Evaluation** — Edge Function + pg\_cron replaces always-on task runner for trigger scheduling (runs every 30 min) * **Canvas Logic Nodes** — Conditional (If-Else) and HTTP Request nodes with branching edges * **Human-Readable Cron Labels** — Friendly labels like "Every weekday at 9:00 AM" across all UIs * **Stale Model Validation** — Warning badge on deprecated model IDs * **Docker Research Crew** — Compose edition for research workflows ### Fixed * Dependency vulnerabilities, canvas logic connections, bypass edge suppression, ESLint compliance ### Documentation * Output Routes docs updated with 9 new destination types * Total output destinations: **16** (HTTP, Slack, Discord, Telegram, Teams, Asana, Trello, Notion, GitHub, Email, SMTP, Linear, Google Sheets, Gmail, Google Docs, Google Calendar) ## \[1.9.1] — 2026-04-23 ### Added * **7-Day Team Trial** — Every new signup gets full Team-tier access for 7 days with dashboard trial banner * **Coolify Deployment Guide** — Step-by-step docs for Coolify v4 deployment * **Cloudflare Turnstile** — Bot protection on login and signup forms ### Fixed * Trial feature gating with `useEELicense` hook fallback * Auth callback PKCE timeout handling ## \[1.9.0] — 2026-04-22 ### Added * **Workflow Templates** — Reusable workflow blueprints that bundle agents, teams, and triggers into single installable packages with `{{variable}}` placeholders * **Template Marketplace** — Browse, filter, and install published templates by category from the Marketplace → Templates tab * **One-Click Install** — Fill in variables and CrewForm auto-creates all agents, team config, and pipeline steps * **Create Template Wizard** — 4-step wizard (Select → Variables → Metadata → Publish) from the Marketplace header or Agent Detail page * **Variable Auto-Detection** — Wizard scans agent prompts for `{{variable}}` patterns and generates variable definitions * **5 Starter Templates** — Weekly Sports Coach, Content Research Pipeline, Daily News Digest, Code Review Assistant, Weekly Report Generator * **Template Triggers** — Templates can include CRON schedules or webhook triggers ### Documentation * New **Workflow Templates** guide added to docs ## \[1.8.2] — 2026-04-11 ### Added * **AG-UI Multi-Step Wizards** — Agents can orchestrate complex, stateful, branching user interactions with 5 input types (approval, confirm\_data, choice, text\_input, form), conditional branching, and cancellation support * **Marketplace: Creator Analytics** — Comprehensive usage dashboard for template authors: install trend charts (30-day), rating distribution, per-agent performance table, and recent reviews feed * **Navigation: Settings Sub-Navigation** — 14 settings tabs migrated to collapsible sidebar groups with URL-based routing (`/settings/:tab`) * **Navigation: Admin Panel Sub-Navigation** — 8 admin tabs migrated to collapsible sidebar group with URL-based routing (`/admin/:tab`) ### Changed * Settings and Admin pages now use sidebar sub-navigation instead of horizontal tab bars * TopBar shows per-section titles for all Settings and Admin sub-pages ## \[1.8.1] — 2026-04-10 ### Added * **Canvas: Copy/Paste Nodes** — `Ctrl+C` / `Ctrl+V` to duplicate agent nodes with auto-connection * **Canvas: Sticky Notes** — Right-click annotations with 5 color presets and persistence * **Canvas: Node I/O Inspector** — Click any agent node to inspect input/output data * **Canvas: Autosave Infrastructure** — Draft config support for Save vs. Publish workflow ### Fixed * Canvas node blur, copy/paste reliability, sticky note persistence across navigation * Orchestrator final answer aggregation and webhook output consistency ## \[1.8.0] — 2026-04-08 ### Added * **Embeddable Chat Widget** — Drop-in ` ``` Place this snippet just before the closing `` tag. ### 3. Self-Hosted Setup If you're self-hosting CrewForm, the widget JS is served directly from your task runner: ```html theme={null} ``` ## Configuration Options ### Script Tag Attributes | Attribute | Required | Default | Description | | --------------- | -------- | ------------------------------ | ------------------------------------------------ | | `data-key` | ✅ | — | Your widget API key (`cf_chat_...`) | | `data-theme` | ❌ | `light` | Theme mode: `light` or `dark` | | `data-position` | ❌ | `bottom-right` | Bubble position: `bottom-right` or `bottom-left` | | `data-url` | ❌ | `https://runner.crewform.tech` | Task runner URL (self-hosted only) | ### Programmatic API For more control, use the JavaScript API: ```javascript theme={null} CrewFormChat.init({ apiKey: 'cf_chat_your_key_here', baseUrl: 'https://runner.crewform.tech', theme: 'dark', // or { mode: 'dark', primaryColor: '#6bedb9' } position: 'bottom-right', }); ``` ### Widget Settings | Setting | Description | | -------------------- | ------------------------------------------------------------------------------- | | **Agent** | Which agent powers the chat | | **Welcome Message** | First message shown when the chat opens | | **Placeholder Text** | Input field placeholder | | **Allowed Domains** | Comma-separated list of domains allowed to use this widget. Empty = all domains | | **Theme** | Light or Dark mode | | **Primary Color** | Brand color for the bubble and user messages | | **Position** | Bottom-right or bottom-left | | **Rate Limit** | Max messages per visitor per hour (default: 20) | ## Security ### Domain Restrictions When you specify allowed domains, the widget server checks the `Origin` header of every request. Only requests from whitelisted domains will be accepted. **Examples:** * `example.com` — allows `example.com` and `www.example.com` * `*.example.com` — allows any subdomain of `example.com` * Leave empty to allow all domains (not recommended for production) ### API Keys Each widget gets a unique `cf_chat_` prefixed API key. This key is visible in the embed script, so **always configure domain restrictions** to prevent unauthorized usage. You can **regenerate** the API key from Settings → Chat Widget if it's compromised. Note that existing deployments will stop working until the embed snippet is updated. ## How It Works ``` ┌──────────────────┐ ┌──────────────┐ ┌─────────────┐ │ Your Website │───▶│ Task Runner │───▶│ LLM API │ │ (Chat Widget) │◀───│ /chat/* │◀───│ (Provider) │ │ │ SSE│ │ │ │ └──────────────────┘ └──────────────┘ └─────────────┘ ``` 1. **Visitor opens the chat bubble** on your website 2. **Widget fetches config** from `/chat/config` (agent name, welcome message) 3. **Visitor sends a message** → `POST /chat/message` 4. **Task runner creates a task** assigned to the configured agent 5. **Agent processes the task** using the LLM provider 6. **Response streams back** via SSE to the widget 7. **Both messages are saved** to the chat session for continuity ## Troubleshooting ### Widget doesn't appear * Check the browser console for errors * Verify the `data-key` attribute matches your widget API key * Ensure the widget is **active** (toggle in Settings → Chat Widget) ### "Origin not allowed" error * Add your domain to the widget's **Allowed Domains** list * Include both `example.com` and `www.example.com` if needed * For local development, add `localhost` ### Messages fail to send * Check that the task runner is running and accessible * Verify the agent has a valid LLM provider key configured * Check the rate limit — visitors are limited to the configured messages per hour ### CORS errors * If self-hosting, ensure your reverse proxy (nginx/Caddy) passes CORS headers * The task runner handles CORS automatically for `/chat/*` endpoints # CLI Tool Source: https://docs.crewform.tech/cli Run CrewForm agents from the command line — scriptable, CI/CD-friendly, Ollama-first. The CrewForm CLI (`npx crewform`) is a standalone command-line tool that lets you create, run, and manage AI agents locally — with optional connectivity to the CrewForm platform. ## Installation ```bash theme={null} # Use directly (zero install) npx crewform # Or install globally npm install -g crewform ``` ## Quick Start ```bash theme={null} # 1. Create an agent config npx crewform init # 2. Run it (defaults to Ollama; set OPENAI_API_KEY for OpenAI, etc.) npx crewform run agent.json "Summarise the latest AI news" # 3. Interactive chat npx crewform chat agent.json ``` ## Commands ### Local Execution | Command | Description | | ------------------------------ | --------------------------------------- | | `crewform run [prompt]` | Run an agent or team from a JSON config | | `crewform chat ` | Interactive chat session with an agent | | `crewform init` | Create a starter agent or team config | | `crewform validate ` | Validate a config file | | `crewform tools` | List available built-in tools | ### Platform (API-Connected) | Command | Description | | ----------------------------- | ---------------------------------------- | | `crewform login` | Authenticate with your CrewForm API key | | `crewform logout` | Remove saved credentials | | `crewform whoami` | Show authenticated user & workspace | | `crewform agents` | List agents in your workspace | | `crewform teams` | List teams in your workspace | | `crewform pull ` | Download agent/team config to local JSON | | `crewform push [prompt]` | Dispatch a task to a remote agent/team | ## Running Agents ### Basic Usage ```bash theme={null} crewform run agent.json "Write a blog post about MCP" ``` ### Input & Output ```bash theme={null} # Read prompt from a file crewform run agent.json --input prompt.txt # Save output to a file crewform run agent.json "Generate a report" --output report.md # Pipe input/output (CI/CD friendly) echo "Review this code" | crewform run agent.json crewform run agent.json "Summarise" > summary.txt # JSON output with token usage and metadata crewform run agent.json "Hello" --json # Quiet mode (suppress streaming, show only final result) crewform run agent.json "Hello" --quiet ``` ## Interactive Chat Start a REPL session with conversation history: ```bash theme={null} crewform chat agent.json ``` **In-chat commands:** | Command | Action | | ---------- | -------------------------------- | | `/clear` | Clear conversation history | | `/history` | Show recent messages | | `/stats` | Show token usage & cost estimate | | `/exit` | End session | ## Pipeline Teams Run multi-agent workflows locally. Agents execute in sequence, with each step's output passed as context to the next. ```bash theme={null} # Create a team config crewform init --team # Run it crewform run team.json "Research and write about GraphQL best practices" ``` ### Team Config Example ```json theme={null} { "name": "Research & Write Team", "mode": "pipeline", "agents": [ { "ref_id": "researcher", "role": "researcher", "agent": { "name": "Researcher", "model": "gpt-4o", "system_prompt": "You are a thorough research agent...", "temperature": 0.3, "tools": ["web_search"] } }, { "ref_id": "writer", "role": "writer", "agent": { "name": "Writer", "model": "gpt-4o", "system_prompt": "You are an expert technical writer...", "temperature": 0.7, "tools": [] } } ], "config": { "steps": [ { "step_name": "Research", "agent_ref": "researcher", "instructions": "Research the given topic thoroughly", "expected_output": "Comprehensive research notes with sources", "on_failure": "stop", "max_retries": 1 }, { "step_name": "Write", "agent_ref": "writer", "instructions": "Write a polished article from the research", "expected_output": "A well-structured blog post", "on_failure": "stop", "max_retries": 0 } ] } } ``` ### Fan-Out (Parallel Execution) Steps with `type: "fan_out"` run multiple agents in parallel, then merge results: ```json theme={null} { "step_name": "Parallel Research", "type": "fan_out", "parallel_agents": ["researcher-1", "researcher-2", "researcher-3"], "merge_agent_ref": "synthesiser", "merge_instructions": "Combine all research into a single report", "fan_out_failure": "continue_on_partial" } ``` **Failure modes:** * `fail_fast` — Stop all branches if any fails * `continue_on_partial` — Collect results from successful branches ## MCP Server Integration Connect agents to external [MCP](/mcp-protocol) servers for dynamic tool discovery: ```bash theme={null} crewform run agent.json --mcp mcp-servers.json "What tables are in my database?" ``` ### MCP Server Config Create a `mcp-servers.json` file: ```json theme={null} [ { "name": "postgres", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"] }, { "name": "filesystem", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"] }, { "name": "remote-tools", "transport": "streamable-http", "url": "https://mcp.example.com/sse" } ] ``` **Supported transports:** `stdio`, `sse`, `streamable-http` ## Platform Integration Connect the CLI to your CrewForm workspace to browse, download, and dispatch agents remotely. ### Authenticate Get your API key from **Settings → API Keys** in the [CrewForm dashboard](https://app.crewform.tech). ```bash theme={null} # Interactive — prompts for your API key crewform login # Non-interactive (CI/CD) crewform login --api-key cf_sk_abc123 # Self-hosted instance crewform login --api-key cf_sk_abc123 --api-url https://my-instance.example.com ``` Credentials are saved to `~/.crewform/config.json`. ### Browse Your Workspace ```bash theme={null} crewform whoami # Show user, workspace, plan crewform agents # List agents (name, model, ID) crewform teams # List teams (mode, member count, ID) # JSON output for scripting crewform agents --json | jq '.items[].name' ``` ### Download Agents Locally Pull an agent or team from the platform and run it locally: ```bash theme={null} # Download agent crewform pull crewform run my-agent.json "Hello" # Download team crewform pull --type team crewform run my-pipeline.json "Research AI trends" ``` ### Dispatch Work Remotely Send a task to a cloud-hosted agent or team without running locally: ```bash theme={null} # Dispatch to an agent crewform push "Write a quarterly report" # Dispatch to a team and wait for completion crewform push --type team --wait "Research and summarise AI trends" # JSON output for CI/CD crewform push "Generate report" --json ``` ## Config Formats The CLI accepts three config formats: ```json theme={null} { "name": "My Agent", "model": "llama3.3", "system_prompt": "You are a helpful assistant.", "temperature": 0.7, "tools": ["web_search"] } ``` Exported via **Agent → Menu → Export** in the dashboard: ```json theme={null} { "format": "crewform-export", "version": 1, "type": "agent", "data": { "name": "My Agent", "model": "gpt-4o", "system_prompt": "...", "temperature": 0.7, "tools": ["web_search"] } } ``` See the [Pipeline Teams](#pipeline-teams) section above for the full team config format. ## Built-in Tools | Tool | Description | Requires | | ------------------ | -------------------------------- | ---------------- | | `web_search` | Search the web via Serper API | `SERPER_API_KEY` | | `http_request` | Make HTTP GET/POST requests | — | | `code_interpreter` | Run JavaScript code in a sandbox | — | | `read_file` | Read a file from a URL | — | | `grammar_check` | Check grammar and spelling | — | Plus any tools discovered from connected MCP servers. ## Environment Variables | Variable | Purpose | | ------------------- | --------------------------------------------------------------- | | `CREWFORM_API_KEY` | API key for platform commands (alternative to `crewform login`) | | `CREWFORM_API_URL` | Custom API URL for self-hosted instances | | `SERPER_API_KEY` | Required for `web_search` tool | | `OPENAI_API_KEY` | OpenAI provider | | `ANTHROPIC_API_KEY` | Anthropic provider | | `GOOGLE_API_KEY` | Google Gemini provider | See the [CLI README](https://github.com/CrewForm/crewform/blob/main/cli/README.md) for the full list of supported providers and their environment variables. ## CI/CD Integration The CLI is designed for automation: ```bash theme={null} # Install globally in CI npm install -g crewform # Run with JSON output for parsing OPENAI_API_KEY=${{ secrets.OPENAI_KEY }} \ crewform run agent.json "Review this PR" --json > review.json # Dispatch to cloud and wait CREWFORM_API_KEY=${{ secrets.CREWFORM_KEY }} \ crewform push $AGENT_ID --wait --json "Generate release notes" > notes.json ``` # Collaboration teams Source: https://docs.crewform.tech/collaboration-teams # Collaboration Teams Collaboration mode lets multiple agents participate in a **shared discussion thread**, taking turns to contribute ideas, critique, build on each other's points, and reach a consensus. Unlike Pipeline (sequential handoffs) or Orchestrator (brain + workers), Collaboration is a peer-to-peer discussion — no hierarchy, just agents talking. ## How It Works ``` User Input (Discussion Topic) │ ▼ ┌─────────────────────────────────────────┐ │ Discussion Thread │ │ │ │ Turn 1: Agent A — opens the discussion │ │ Turn 2: Agent B — responds, builds on │ │ Turn 3: Agent C — critiques, adds more │ │ Turn 4: Agent A — responds to critique │ │ Turn 5: Agent B — "I agree, ..." │ ← consensus phrase detected │ Turn 6: Agent C — "I agree, ..." │ ← consensus reached → stop │ │ └─────────────────────────────────────────┘ │ ▼ Final Output (full thread + last contribution) ``` Each agent sees the full conversation history before contributing. The run ends when a termination condition is met (max turns, consensus, or facilitator decision). ## Creating a Collaboration Team 1. Navigate to **Teams → New Team** 2. Give it a name and description 3. Select **Collaboration** as the team mode 4. Add at least 2 participant agents 5. Configure speaker selection, termination, and turn limits ## Configuration ### Participant Agents Add at least 2 agents to participate in the discussion. Each agent brings its own system prompt — their expertise, perspective, or role in the conversation. **Example: Strategy Review Team** * **Alex (Optimist)** — "You look for opportunities, upside, and growth potential. You challenge conservative assumptions." * **Jordan (Devil's Advocate)** — "You stress-test ideas by identifying risks, edge cases, and potential failures." * **Sam (Pragmatist)** — "You focus on feasibility, implementation, and resource constraints." ### Speaker Selection Determines how the next speaker is chosen each turn. | Strategy | Description | Best For | | --------------- | ---------------------------------------------------------------------------- | --------------------------------------------------- | | **Round Robin** | Agents take turns in order (A → B → C → A → ...) | Structured discussions, equal contribution | | **LLM Selects** | An LLM picks the most relevant next speaker based on the conversation so far | Dynamic discussions where expertise varies by topic | | **Facilitator** | A designated facilitator agent decides who speaks next | Moderated panels, interview-style discussions | #### Round Robin Simple and predictable. Each agent speaks in the order they were added. #### LLM Selects After each turn, a meta-LLM call reads the recent conversation and picks the agent whose expertise is most relevant to respond next. Falls back to round robin if the LLM returns an invalid agent ID. > **Note:** LLM Select adds one extra LLM call per turn for speaker selection. Factor this into cost estimates. #### Facilitator One agent is designated as the **facilitator**. The facilitator speaks on the first turn (to set the stage) and then directs the discussion by choosing who speaks next. Requires selecting a **Facilitator Agent** from the participant list. The facilitator receives additional context about the available participants and is asked to select the next speaker after every turn. ### Termination Condition Determines when the discussion ends. | Condition | Description | | ------------------------ | --------------------------------------------------------------------------------- | | **Max Turns** | Discussion ends after a fixed number of turns | | **Consensus** | Discussion ends when the majority of recent speakers include the consensus phrase | | **Facilitator Decision** | Discussion ends when the facilitator says `DISCUSSION COMPLETE` | #### Max Turns The simplest option. Set a turn limit and the discussion runs until it's reached. Good for open-ended brainstorms where you want a fixed amount of output. #### Consensus Each agent is instructed to include a configurable **consensus phrase** in their response when they agree with the group's direction. When a majority of recent speakers include the phrase, the discussion terminates. Configure the consensus phrase (default: `"I agree with this approach"`). Keep it distinctive enough that agents won't say it accidentally. ``` Good: "I agree with this approach" — specific, unlikely to appear casually Avoid: "yes" — too common, will trigger false positives ``` #### Facilitator Decision The facilitator can end the discussion at any time by including `DISCUSSION COMPLETE` in their message. Use this when you want a human-readable signal for when consensus or sufficient exploration has been reached. ### Configuration Fields | Field | Description | Default | | ------------------------- | ----------------------------------------------------------- | ------------------------------ | | **Participant Agents** | Agents in the discussion (min 2) | Required | | **Speaker Selection** | How the next speaker is chosen | `round_robin` | | **Max Turns** | Maximum number of speaking turns before the discussion ends | 10 | | **Termination Condition** | What stops the discussion early | `max_turns` | | **Consensus Phrase** | Text agents include to signal agreement | `"I agree with this approach"` | | **Facilitator Agent** | Agent who directs the discussion (Facilitator mode only) | Optional | ## Output Collaboration runs produce two things: 1. **Final Contribution** — the last agent's message, treated as the primary output 2. **Full Discussion Thread** — every turn, labelled by agent name This means you get both a concise final thought *and* the full deliberation history. The full thread is useful for: * Understanding how the conclusion was reached * Reviewing dissenting views that were considered * Using the discussion as research material ## Team Memory Like orchestration teams, collaboration teams persist memory across runs. After each completed run, the output is stored. On the next run covering a similar topic, relevant past discussions are surfaced in context on the first turn. This allows teams to build on previous sessions — a strategy review team, for example, will remember past conclusions and avoid re-covering ground. ## Example: Architecture Review A 3-agent collaboration team for reviewing technical architecture proposals: **Participants:** 1. **Alex (Security)** — "You are a security engineer. You review designs for attack vectors, data exposure risks, and compliance gaps." 2. **Jordan (Performance)** — "You are a performance engineer. You review for bottlenecks, scalability limits, and latency concerns." 3. **Sam (Practicality)** — "You are a senior engineer. You assess whether the proposed design is actually buildable with the team's current skills and stack." **Settings:** * Speaker Selection: **Round Robin** * Max Turns: **9** (3 full rounds) * Termination: **Consensus** (`"I approve this architecture"`) **Typical run:** 1. Alex opens: security concerns about the proposed auth design 2. Jordan responds: performance implications of the auth overhead 3. Sam: "the team can implement this — we already have JWT middleware" 4. Alex: "agreed on JWT, but we need rate limiting — I approve this architecture" 5. Jordan: "rate limiting noted, adding to non-functional requirements — I approve this architecture" 6. Sam: "I approve this architecture" → **Consensus reached, discussion ends** ## Visual Workflow Builder (Canvas) Collaboration teams include a **Visual Workflow Builder** — an interactive canvas for designing and monitoring your discussion participant graph in real-time. See the full [Visual Workflow Builder Guide](./visual-workflow-builder.md) for complete documentation. ### Canvas Features * **Drag agents** from the sidebar onto the canvas to add participants * **Connect nodes** by dragging edges to define speaking relationships * **Right-click context menu** — Delete, Auto-layout, Fit View * **Glassmorphism styling** — frosted glass nodes with hover lift effects * **Searchable sidebar** — filter agents by name or model ### Live Execution Visualization During a discussion run, the canvas shows which agent is currently speaking: * **Node states** — Idle, Running (blue pulse), Completed (green ✓), Failed (red ✕) * **Camera auto-follow** — Canvas pans to the agent currently taking their turn * **Transcript panel** (`T`) — Real-time discussion thread with color-coded agent messages * **Tool heatmap** — Tool usage stats across the discussion ### Keyboard Shortcuts Press `?` for the full shortcuts overlay. Key shortcuts: `F` (fit view), `L` (auto-layout), `T` (transcript), `⌘Z` (undo), `⌘A` (select all). ### Auto-Layout Click **Auto-Layout** or press `L` for a **left-to-right** layout — reflecting the peer-to-peer discussion flow. ### Position Persistence Node positions are saved automatically and restored when you revisit — stored in `teams.config` JSONB column. ## Tips * **Give agents distinct perspectives.** The discussion is only valuable if agents genuinely disagree and challenge each other. Agents with identical system prompts will produce repetitive turns. * **Max turns × average tokens ≈ your cost.** A 10-turn discussion with 3 agents will generate 10 LLM calls, each with a growing conversation history (every agent sees all previous turns). Watch out for token costs on long discussions. * **Consensus phrase needs to be intentional.** Agents include the phrase deliberately when they agree. Make it specific and natural enough that a reasonable agent would say it, but not so common that it fires by accident. * **Facilitator Decision is great for open-ended exploration.** Let the discussion run freely and have the facilitator close it when they judge that enough ground has been covered. * **Use LLM Select for expert panels.** When agents have narrow specialisations, LLM Select routes questions to the most relevant expert rather than forcing everyone to respond to everything. ## Related * [Pipeline Teams](./pipeline-teams.md) — Sequential steps with fixed agent handoffs * [Orchestration Teams](./orchestration-teams.md) — Brain agent delegates to workers dynamically # Coolify deployment Source: https://docs.crewform.tech/coolify-deployment # Deploy with Coolify [Coolify](https://coolify.io) is an open-source, self-hostable alternative to Vercel, Netlify, and Heroku. It provides a clean UI for managing Docker deployments on your own servers — no vendor lock-in. This guide walks you through deploying CrewForm on Coolify. ## Prerequisites * A running **Coolify v4** instance ([installation guide](https://coolify.io/docs/installation)) * A server connected to Coolify with **≥ 2 GB RAM** (4 GB recommended) * A **Supabase project** (or self-hosted PostgreSQL 15+) ## Method 1: Docker Compose (Recommended) This deploys the full CrewForm stack (frontend, task-runner, postgres, migrations) using the built-in `docker-compose.yml`. ### Step 1 — Create a New Resource 1. Open your Coolify dashboard 2. Click **+ Add New Resource** 3. Select **Docker Compose** 4. Choose **Git Repository** as the source ### Step 2 — Connect the Repository | Field | Value | | ----------------------- | -------------------------------------- | | Repository URL | `https://github.com/CrewForm/crewform` | | Branch | `main` | | Docker Compose Location | `docker-compose.yml` | Click **Check Repository** to validate. ### Step 3 — Configure Environment Variables In the **Environment Variables** tab, add the required variables: ```env theme={null} # ─── Required ───────────────────────────────── POSTGRES_PASSWORD=your-strong-database-password VITE_SUPABASE_URL=https://your-project.supabase.co VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs... SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIs... # ─── Recommended ────────────────────────────── VITE_APP_URL=https://crewform.yourdomain.com ENCRYPTION_KEY=your-32-byte-hex-key # ─── Optional (LLM fallback keys) ───────────── OPENAI_API_KEY=sk-... ANTHROPIC_API_KEY=sk-ant-... GOOGLE_GENERATIVE_AI_API_KEY=AIza... ``` > **💡** Generate a secure encryption key: `openssl rand -hex 32` ### Step 4 — Configure Networking In the **Network** tab: 1. Set the **Exposed Port** to `3000` (the frontend port) 2. Add your custom domain (e.g. `crewform.yourdomain.com`) 3. Enable **HTTPS** — Coolify handles TLS certificates automatically via Let's Encrypt ### Step 5 — Deploy Click **Deploy**. Coolify will: 1. Clone the repository 2. Run `docker compose up -d` 3. Execute database migrations automatically (via the `migrate` container) 4. Start the frontend on port 3000 5. Start the task-runner for AI execution Monitor progress in the **Logs** tab. ### Step 6 — Verify Visit your configured domain. You should see the CrewForm login screen. Check individual service logs: * **Frontend** → nginx serving the SPA * **Task Runner** → should show `[runner] Polling for tasks...` * **Migrate** → should show `All migrations applied` and exit *** ## Method 2: Git-Based (Frontend Only) If you're using **Supabase Cloud** and only need to deploy the frontend + task-runner (no local Postgres), you can use Coolify's Git-based deployment. ### Step 1 — Create a Nixpacks Resource 1. Click **+ Add New Resource** 2. Select **Application** 3. Choose **Public Repository** 4. Enter: `https://github.com/CrewForm/crewform` 5. Branch: `main` ### Step 2 — Build Settings | Setting | Value | | --------------- | ----------------- | | Build Pack | **Nixpacks** | | Install Command | `npm install` | | Build Command | `npm run build` | | Start Command | `npm run preview` | | Port | `3000` | ### Step 3 — Environment Variables Add the same Supabase variables from Method 1 (skip `POSTGRES_*` variables since you're using Supabase Cloud). ### Step 4 — Deploy Click **Deploy**. Coolify will build and serve the frontend. > **⚠️ Note:** You'll need to deploy the task-runner separately as a Docker container, or run it on the same server via Docker Compose. The task-runner is required for AI task execution. *** ## Updating ### Automatic Updates Coolify supports **webhook-based auto-deploy**: 1. Go to your resource **Settings** 2. Enable **Auto Deploy** on push 3. Add the Coolify webhook URL to your GitHub repository's webhooks Every push to `main` will trigger a rebuild. ### Manual Updates 1. Open your resource in Coolify 2. Click **Redeploy** 3. Coolify pulls the latest code, rebuilds, and runs migrations *** ## Adding Ollama (Local AI) To run local models alongside CrewForm on the same Coolify server: ### Step 1 — Add Ollama as a Service 1. Create a new **Docker** resource in Coolify 2. Use the image: `ollama/ollama` 3. Mount a volume: `/root/.ollama` → `ollama_data` 4. Expose port: `11434` ### Step 2 — Pull Models Connect to the Ollama container and pull your preferred models: ```bash theme={null} # Via Coolify's terminal or SSH docker exec -it ollama pull llama3.3 docker exec -it ollama pull deepseek-r1:8b ``` ### Step 3 — Connect in CrewForm 1. Go to **Settings → LLM Setup** in CrewForm 2. Find **Ollama (Local)** in the provider list 3. Enter any value as the API key (e.g. `ollama`) 4. If Ollama and CrewForm are on the same Coolify server, the task-runner reaches Ollama at `http://ollama:11434/v1` (Docker network) or `http://host.docker.internal:11434/v1` ### GPU Passthrough If your server has an NVIDIA GPU, add to the Ollama service in Coolify: ```yaml theme={null} deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] ``` *** ## Troubleshooting ### Frontend shows blank page * Verify `VITE_SUPABASE_URL` and `VITE_SUPABASE_ANON_KEY` are set in Coolify's environment variables * Check the frontend container logs in Coolify ### Task runner not processing * Ensure `SUPABASE_SERVICE_ROLE_KEY` is set * Check the task-runner logs in Coolify's **Logs** tab * Verify network connectivity to Supabase ### Migrations not running * Check the `migrate` container logs — it runs once and exits * To re-run, restart the migrate service from Coolify ### Domain not resolving * Ensure your DNS A record points to the Coolify server IP * Check that Coolify's proxy (Traefik) is running: Coolify → Settings → Proxy > **Need help?** Join our [Discord](https://discord.gg/TAFasJCTWs) or open an [issue on GitHub](https://github.com/CrewForm/crewform/issues). # Discord integration Source: https://docs.crewform.tech/discord-integration # Discord Integration Connect a Discord server to CrewForm so users can trigger agents and pipeline teams directly from Discord using slash commands. ## How It Works CrewForm's Discord integration uses a **slash command bot** registered in the Discord Developer Portal. Once connected, users can run: | Command | Description | | ------------------------ | --------------------------------------------------- | | `/connect code:` | Link a Discord channel to a CrewForm output route | | `/ask prompt:` | Send a task to the connected agent or pipeline team | Responses use Discord's **deferred message** pattern — Discord shows a "thinking…" indicator while CrewForm processes the request, then follows up with the result. This avoids Discord's 3-second response timeout. *** ## Setup: Managed Bot (Recommended) The managed bot uses CrewForm's own Discord application. No separate bot registration needed. ### Step 1: Invite the Bot Before connecting, invite the CrewForm bot to your Discord server: 1. Go to **Settings → Channels** in CrewForm 2. Click **Add Channel → Discord** 3. Click the **Invite Bot** link shown in the setup panel 4. Select your Discord server and authorise the bot (requires `Manage Server` permission) > ⚠️ **The bot must be invited before you can use `/connect`.** If you skip this step, slash commands won't appear in your server. ### Step 2: Get Your Connect Code 1. In **Settings → Channels**, click **New Channel** and choose **Discord** 2. Toggle **Managed Bot** on 3. Optionally set a **Default Agent** or **Default Team** — this is what `/ask` will call 4. Save the channel — a **connect code** is generated ### Step 3: Connect the Discord Channel In your Discord server: ``` /connect code: ``` You'll see a confirmation: ``` ✅ Connected! Use `/ask prompt:` to send requests to your agent. ``` ### Step 4: Test It ``` /ask prompt:Summarise the latest trends in AI tooling ``` CrewForm will show `⏳ Processing your request...` then follow up with the agent's response. *** ## Setup: Bring Your Own Bot (BYOB) If you want full control over the Discord application (custom name, avatar, permissions), you can register your own bot. ### 1. Create a Discord Application 1. Go to [discord.com/developers/applications](https://discord.com/developers/applications) 2. Click **New Application** → give it a name (e.g., "My CrewForm Bot") 3. Go to **Bot** tab → click **Add Bot** 4. Copy the **Bot Token** 5. Go to **General Information** → copy the **Public Key** ### 2. Register Slash Commands Run this once to register the `/connect` and `/ask` commands on your bot: ```bash theme={null} # Replace with your App ID and Bot Token APP_ID="your_application_id" BOT_TOKEN="your_bot_token" curl -X POST "https://discord.com/api/v10/applications/${APP_ID}/commands" \ -H "Authorization: Bot ${BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "name": "connect", "description": "Link this Discord channel to CrewForm", "options": [{ "name": "code", "description": "Connect code from CrewForm", "type": 3, "required": true }] }' curl -X POST "https://discord.com/api/v10/applications/${APP_ID}/commands" \ -H "Authorization: Bot ${BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "name": "ask", "description": "Send a task to your CrewForm agent", "options": [{ "name": "prompt", "description": "Your question or task", "type": 3, "required": true }] }' ``` ### 3. Set the Interactions Endpoint 1. In the Discord Developer Portal, go to **General Information** 2. Set **Interactions Endpoint URL** to: ``` https://.supabase.co/functions/v1/channel-discord ``` 3. Click **Save** — Discord will ping the URL to verify Ed25519 signature verification > ⚠️ Discord **requires** a valid `DISCORD_PUBLIC_KEY` environment variable on your Supabase project for this step to pass. Set it in your Supabase project's **Edge Function secrets** or your self-hosted `.env`. ### 4. Configure in CrewForm In **Settings → Channels → New Channel → Discord**: * Toggle **Managed Bot** OFF * Paste your **Bot Token** and **Guild ID** * Set a Default Agent or Team * Invite your bot to your Discord server with the OAuth2 URL from the Developer Portal *** ## Environment Variables | Variable | Required | Description | | -------------------- | -------------------------------- | ---------------------------------------- | | `DISCORD_BOT_TOKEN` | Managed mode only | Token for the shared CrewForm bot | | `DISCORD_PUBLIC_KEY` | BYOB mode (Ed25519 verification) | Public key from Discord Developer Portal | For self-hosted deployments, add these to your `.env` file. See the [Self-Hosting Guide](./self-hosting.md). *** ## Troubleshooting ### `/connect` or `/ask` commands don't appear in my server The bot hasn't been invited, or slash commands haven't been registered yet. Follow Steps 1–2 in the managed bot setup, or re-run the `curl` commands in the BYOB setup. ### "Invalid connect code" error * Double-check the code from **Settings → Channels** — codes are single-use and expire if not used * Ensure the channel platform is set to **Discord** in CrewForm ### "No agent configured" error The channel's `/connect` was completed but no Default Agent or Default Team was assigned. Go to **Settings → Channels**, edit the channel, and set a default. ### Discord responds with 401 Unauthorized The `DISCORD_PUBLIC_KEY` environment variable is missing or incorrect. Verify it matches the **Public Key** in your Discord Developer Portal → General Information. ### Responses time out or never arrive CrewForm uses deferred responses — Discord shows "thinking…" while the task runs. If no followup arrives: * Check task-runner logs: `docker compose logs -f task-runner` * Ensure the task-runner has a valid LLM API key for the assigned agent's provider *** ## Related * [Channels](./channels.md) — Overview of all inbound channels (Telegram, Slack, Email) * [Output Routes](./output-routes.md) — Push agent results outbound to Discord and other destinations # Run Your First Agent System Source: https://docs.crewform.tech/first-agent-system Use the golden-path Research Brief demo to run a real multi-agent workflow in CrewForm. # Run Your First Agent System This is the fastest way to see CrewForm work end-to-end. You will set up one provider key, activate the prebuilt Research Brief Pipeline, run a real team workflow, and inspect the output. The demo uses the normal CrewForm execution path. It creates real agents, a real pipeline team, and a real team run that is picked up by the task runner. ## What You Will Run The golden-path demo creates a 3-step pipeline: | Step | Agent | What It Does | | ----------- | ---------------- | ---------------------------------------------------------------------------- | | Research | Research Analyst | Builds market context, findings, trends, assumptions, and verification notes | | Analyze | Data Analyst | Prioritizes insights, opportunities, risks, and recommended structure | | Write Brief | Content Writer | Produces a polished markdown executive brief | Default prompt: ```text theme={null} Research the market for AI customer support tools and produce a short executive brief. ``` ## 1. Start CrewForm Use the hosted app: ```text theme={null} https://app.crewform.tech ``` Or run locally: ```bash theme={null} git clone https://github.com/CrewForm/crewform.git cd crewform npm install cp .env.example .env.local npm run dev ``` The task runner must also be running for real execution: ```bash theme={null} cd task-runner npm install cp .env.example .env # Add SUPABASE_URL / VITE_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY npm run dev ``` ## 2. Add One Provider Key Open **Settings → LLM Setup** and add an active OpenAI key. The demo agents use `gpt-4o-mini` by default so the run is fast and low-cost. You can change the models later from the agent configuration pages. ## 3. Activate the Demo Workspace Return to **Dashboard** and choose **Activate Demo Workspace**. CrewForm will create: * 5 demo agents * 1 Research Brief Pipeline team * Team membership and pipeline step wiring The demo data is removable from the dashboard banner at any time. ## 4. Run the Demo After the demo is active, choose **Run Demo** from the dashboard banner. CrewForm will create a real `team_run` and open the run detail page. You should see: * Current pipeline step * Agent handoffs * Running/completed status * Final markdown output * Token and cost totals when the run completes ## 5. Inspect the Result When the run finishes, review: * The final executive brief * Step-by-step messages * Token usage and estimated cost * Any error or retry details if a step failed From there, open the team page to customize the prompt, agents, model, tools, or pipeline steps. ## Troubleshooting | Problem | What To Check | | ----------------------------------------------- | ------------------------------------------------------------------------- | | The **Run Demo** button says **Add OpenAI Key** | Add and activate an OpenAI provider key in Settings | | The run stays pending | Make sure the task runner is running and connected to Supabase | | The run fails immediately | Check that your provider key is valid and the selected model is available | | The output is too generic | Add more detail to the run prompt or enable tools/knowledge sources | ## Next Steps * [Pipeline Teams](/pipeline-teams) — Understand how fixed multi-agent workflows execute * [Visual Workflow Builder](/visual-workflow-builder) — Edit and observe the workflow on the canvas * [Observability](/observability) — Add Langfuse or an OTLP backend for traces * [API Reference](/api-reference) — Trigger runs from scripts and external systems # Knowledge Base (RAG) Source: https://docs.crewform.tech/knowledge-base Upload documents, auto-chunk and embed, and let agents search via retrieval-augmented generation with hybrid search and metadata filtering ## Overview CrewForm's **Knowledge Base** enables Retrieval-Augmented Generation (RAG) — upload documents, and agents automatically search relevant content when answering questions or completing tasks. ## How It Works ``` Upload Document → Text Extraction → Chunking → Embedding (1536-dim) ↓ Agent Task → knowledge_search tool → Hybrid Search → Reranked Results ``` 1. Upload documents to the Knowledge Base 2. CrewForm automatically chunks the text and generates vector embeddings 3. Enable the `knowledge_search` tool on your agents 4. During task execution, agents semantically search the knowledge base for relevant context ## Supported File Types | Format | Extension | Description | | ---------- | --------- | --------------------------------- | | Plain Text | `.txt` | Raw text files | | Markdown | `.md` | Markdown documents | | CSV | `.csv` | Tabular data (rows become chunks) | | JSON | `.json` | Structured data | ## Uploading Documents 1. Navigate to **Knowledge Base** from the sidebar 2. Click **Upload Document** 3. Select your file — upload begins automatically 4. The document status progresses: `pending` → `processing` → `ready` During processing, CrewForm: * Extracts text content from the file * Splits into chunks (optimized for retrieval quality) * Generates vector embeddings using OpenAI's `text-embedding-3-small` model (1536 dimensions) * Builds full-text search vectors (`tsvector`) for hybrid retrieval * Stores chunks with embeddings in pgvector for fast similarity search ## Metadata Tags Organize your documents with tags to improve retrieval precision. ### Adding Tags 1. On the Knowledge Base page, click the **tag icon** next to any document 2. Type a tag name and press Enter (e.g., `FAQ`, `Technical`, `Policy`) 3. Tags are saved immediately ### Filtering by Tags When searching, you can filter results to only include chunks from documents with specific tags: * In the **Retrieval Tester**, select tags from the dropdown * Via the API, pass `tags: ["FAQ", "Technical"]` to the search endpoint * In the `knowledge_search` agent tool, tags are passed via the agent's configuration Tags are indexed with GIN for fast filtering even with large document collections. ## Search Modes CrewForm supports two search modes: ### Vector Search (Default) Standard cosine similarity search against chunk embeddings: * **Embedding model:** OpenAI `text-embedding-3-small` (1536 dimensions) * **Index type:** IVFFlat (lists = 100) for fast approximate nearest-neighbor search * **Default top-K:** 5 results * **Scope:** Workspace-level, optionally filtered by document IDs or tags ### Hybrid Search Combines vector similarity with PostgreSQL full-text search for better recall: ``` Final Score = (vector_weight × cosine_similarity) + (text_weight × ts_rank) ``` * **Default weights:** 70% vector / 30% full-text * **Over-fetch strategy:** Retrieves 2× the requested results from each method, then reranks and deduplicates * **Full-text search:** Uses PostgreSQL `tsvector` with `ts_rank_cd` for keyword matching * **Best for:** Queries mixing semantic meaning with specific keywords, technical terms, or entity names Toggle between search modes in the Retrieval Tester or via the API. ## Retrieval Tester The **Retrieval Tester** is an interactive playground for evaluating search quality before deploying to agents. ### How to Use 1. Navigate to **Knowledge Base** and open the **Test Retrieval** panel 2. Type a query in the search box 3. Configure: * **Search Mode** — Toggle between `vector` and `hybrid` * **Top-K** — Number of results (1–20) * **Filter by Document** — Restrict to specific documents * **Filter by Tags** — Restrict to documents with specific tags 4. Click **Search** to see results ### Reading Results Each result displays: * **Similarity Score** — Color-coded bar (green = high, yellow = medium, red = low) * **Source Document** — Which document the chunk came from * **Chunk Preview** — The matched text content * **Response Time** — How long the search took Use the tester to: * Verify that the right documents surface for expected queries * Compare vector vs hybrid search quality * Tune top-K and tag filters before enabling on agents ## Enabling Knowledge Search on Agents 1. Open the agent's configuration 2. In the **Tools** section, enable `knowledge_search` 3. Optionally restrict to specific documents via **Knowledge Base IDs** in the agent config 4. Save — the agent can now search your documents during task execution ### How Agents Use It When an agent has `knowledge_search` enabled, it can call: ``` knowledge_search(query: "What is our refund policy?") ``` This returns the top-K most semantically similar chunks from your uploaded documents, which the agent uses as context for its response. ## API Endpoint You can query the knowledge base directly without creating agent tasks: ```bash theme={null} POST /kb/search Authorization: Bearer { "workspace_id": "your-workspace-id", "query": "What is our refund policy?", "mode": "hybrid", "top_k": 5, "tags": ["FAQ"], "document_ids": [] } ``` **Response:** ```json theme={null} { "results": [ { "id": "chunk-uuid", "content": "Our refund policy allows returns within 30 days...", "similarity": 0.89, "document_name": "refund-policy.md" } ], "mode": "hybrid", "response_time_ms": 42 } ``` ## Managing Documents From the Knowledge Base page you can: * **View** — See all uploaded documents with status, file size, and chunk count * **Tag** — Add metadata tags for filtering * **Delete** — Remove a document and all its chunks (cascading delete) * **Monitor** — Real-time status updates during processing * **Test** — Use the Retrieval Tester to evaluate search quality ## Database The Knowledge Base uses two tables: | Table | Description | | --------------------- | ---------------------------------------------------------------------------- | | `knowledge_documents` | Uploaded file metadata (name, size, status, chunk count, tags) | | `knowledge_chunks` | Embedded text chunks with 1536-dim vectors and tsvector for full-text search | Both tables have workspace-scoped RLS. Two RPC functions handle search: * `match_knowledge_chunks` — Vector-only cosine similarity search * `hybrid_search_knowledge` — Combined vector + full-text search with reranking ## Tier Limits | Plan | Max Documents | | ----- | ------------- | | Free | 3 | | Pro | 25 | | Team+ | Unlimited | # MCP Protocol Source: https://docs.crewform.tech/mcp-protocol Connect agents to thousands of external tool servers via the Model Context Protocol ## Overview CrewForm is a **full MCP participant** — both as a client (consuming external tools) and as a server (exposing agents as tools). Your agents can discover and autonomously invoke tools from any MCP-compatible server during task execution, giving them access to databases, APIs, file systems, code execution environments, and thousands of third-party services. MCP is one of three agentic protocols CrewForm supports, alongside [A2A](/a2a-protocol) (agent-to-agent) and [AG-UI](/ag-ui-protocol) (agent-to-frontend). ## Architecture CrewForm implements the full MCP client lifecycle using the official `@modelcontextprotocol/sdk`: ``` ┌─────────────────────────────────────────────────────────────────┐ │ Task Execution (executor.ts) │ │ │ │ 1. Agent has mcp: tools enabled │ │ 2. Task Runner fetches MCP server configs from DB │ │ 3. MCP Client connects to each server (HTTP/SSE/stdio) │ │ 4. Tools discovered via tools/list │ │ 5. Tool definitions injected into LLM function calling schema │ │ 6. LLM invokes MCP tools → mcpClient.callMcpTool() │ │ 7. Results flow back into the agent's reasoning loop │ │ 8. MCP clients disconnected after task completes │ └─────────────────────────────────────────────────────────────────┘ ``` ## Runtime Execution When a task runs, CrewForm's task runner **automatically connects to configured MCP servers and makes their tools available** to the agent. This happens transparently — the agent's LLM sees MCP tools alongside built-in tools and can invoke them as part of its reasoning. ### What Happens During a Task Run 1. **Tool Detection** — The executor checks if the agent has any `mcp:` tools enabled 2. **Server Connection** — For each configured MCP server, the task runner establishes a connection using the appropriate transport (HTTP, SSE, or stdio) 3. **Tool Discovery** — Calls `tools/list` on each connected server to get available tool definitions (name, description, input schema) 4. **Schema Injection** — Discovered MCP tool definitions are merged into the LLM's function calling schema alongside built-in tools 5. **Autonomous Execution** — When the LLM decides to call an MCP tool, the task runner routes the call through `callMcpTool()` with the tool name and arguments 6. **Result Processing** — Tool results flow back into the agent's context, informing the next reasoning step 7. **Cleanup** — All MCP client connections are disconnected after the task completes Agents don't need special configuration to use MCP tools during execution. Just enable the `mcp:` tools on the agent and the task runner handles connection, discovery, execution, and cleanup automatically. ### Example: Agent Using GitHub MCP Tools ``` Agent: "I need to check the latest issues in the crewform repo" ↓ LLM decides to call: mcp:github/list_issues ↓ Task Runner → mcpClient.callMcpTool("github", "list_issues", { repo: "crewform/crewform" }) ↓ MCP Server (GitHub) returns issue data ↓ Agent receives results and continues reasoning ``` ## Supported Transports | Transport | Description | Use Case | | ----------------- | ------------------------------ | --------------------------- | | `streamable-http` | HTTP-based streaming (default) | Cloud-hosted MCP servers | | `sse` | Server-Sent Events | Real-time streaming servers | | `stdio` | Standard I/O | Local process-based servers | ## Adding an MCP Server 1. Go to **Settings → MCP Servers** 2. Click **Add Server** 3. Fill in: * **Name** — Display name (e.g. "GitHub Tools") * **URL** — Server URL or command (e.g. `https://mcp.example.com`) * **Transport** — `streamable-http`, `sse`, or `stdio` * **Config** (optional) — JSON object with auth headers, env vars, or command arguments 4. Click **Save** — CrewForm discovers and caches available tools ### Config Examples **HTTP server with auth:** ```json theme={null} { "headers": { "Authorization": "Bearer your-token" } } ``` **stdio server with env vars:** ```json theme={null} { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "ghp_xxx" } } ``` ## Enabling MCP Tools on Agents 1. Open the agent's configuration 2. In the **Tools** section, you'll see discovered MCP tools listed as `mcp:server-name/tool-name` 3. Toggle the tools you want the agent to use 4. Save — the agent can now use those tools autonomously during task execution ## Tool Discovery When you add or refresh an MCP server, CrewForm: 1. Connects to the server using the configured transport 2. Calls the `tools/list` method to discover available tools 3. Caches the tool definitions (name, description, input schema) 4. Makes them available in the agent configuration UI Cached tools are refreshed automatically when the server configuration changes. You can also manually refresh from the settings panel. ## Popular MCP Servers | Server | Description | | ------------------------------------------- | ------------------------- | | `@modelcontextprotocol/server-github` | GitHub repos, issues, PRs | | `@modelcontextprotocol/server-filesystem` | Local file system access | | `@modelcontextprotocol/server-postgres` | PostgreSQL queries | | `@modelcontextprotocol/server-brave-search` | Brave web search | | `@modelcontextprotocol/server-slack` | Slack messaging | Browse more at [github.com/modelcontextprotocol/servers](https://github.com/modelcontextprotocol/servers). ## Database MCP servers are stored in the `mcp_servers` table with workspace-scoped RLS. Each server record includes: * Connection config (URL, transport, auth) * Cached tool definitions * Enabled/disabled status ## MCP Server Publishing CrewForm can also act as an MCP **Server** — exposing your agents as tools that Claude Desktop, Cursor, and other MCP clients can call. This makes CrewForm a **full bidirectional MCP participant**: consuming external tools and publishing agents as tools. Learn how to expose your agents as MCP tools for external clients. # MCP Server Publishing Source: https://docs.crewform.tech/mcp-server-publishing Expose your CrewForm agents as MCP tools for Claude Desktop, Cursor, and other MCP clients ## Overview CrewForm can act as an **MCP Server**, exposing your agents as tools that any MCP-compatible client can discover and call. This means Claude Desktop, Cursor, other AI frameworks, or custom integrations can use your CrewForm agents as tools — without writing a single line of code. This is the **reverse** of MCP Client support. MCP Client lets your agents *use* external tools. MCP Server Publishing lets *external clients* use your agents as tools. ``` External MCP Client → POST /mcp → Task Runner → Agent Execution (Claude Desktop, JSON-RPC Auth + Create task, Cursor, etc.) Protocol Routing poll for result ``` ## Quick Start ### 1. Generate an MCP API Key 1. Go to **Settings → MCP Servers** 2. Scroll to **MCP Server Publishing** 3. Click **Generate MCP API Key** 4. Copy the key — it's only shown once ### 2. Publish Your Agents 1. Open any agent's detail page 2. Click the **MCP Publish** button in the toolbar 3. The agent now appears as an MCP tool ### 3. Connect Your Client In the **MCP Server Publishing** section of Settings, you'll see an auto-generated config snippet. Copy it into your client: **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`): ```json theme={null} { "mcpServers": { "crewform": { "url": "https://runner.crewform.tech/mcp", "headers": { "Authorization": "Bearer cf_mcp_your_key_here" } } } } ``` **Cursor** (Settings → MCP): Add a new MCP server with your endpoint URL and Bearer token auth header. ## How It Works When an MCP client connects to your CrewForm `/mcp` endpoint: 1. **`initialize`** — Client establishes a session. CrewForm returns its server capabilities and protocol version. 2. **`tools/list`** — Client discovers available tools. Each MCP-published agent becomes a tool with: * **name** — Derived from agent name (lowercase, underscored, max 64 chars) * **description** — The agent's description * **inputSchema** — `{ message: string }` — the prompt to send to the agent 3. **`tools/call`** — Client invokes a tool. CrewForm creates a task, assigns it to the agent, and polls for completion. The agent's output is returned as the tool result. ## Authentication MCP Server requests are authenticated via **Bearer tokens**: ``` Authorization: Bearer cf_mcp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` The server accepts two types of API keys: * **MCP Server keys** (`provider: 'mcp-server'`) — Dedicated keys generated from the UI * **A2A keys** (`provider: 'a2a'`) — Existing A2A API keys also work as a fallback Each key is scoped to a workspace. Only agents in that workspace are exposed. ## Managing API Keys | Action | How | | -------------- | --------------------------------------------------------------------- | | **Generate** | Settings → MCP Servers → MCP Server Publishing → Generate MCP API Key | | **Regenerate** | Click "Regenerate" next to the existing key (invalidates the old one) | | **Revoke** | Click "Revoke" to delete the key entirely | Regenerating or revoking a key immediately invalidates it. All connected MCP clients will need to be updated with the new key. ## Published Agent List The **MCP Server Publishing** section in Settings shows all agents currently exposed as MCP tools, including their tool names. This lets you verify exactly what external clients will see when they call `tools/list`. ## Transport CrewForm's MCP Server uses **Streamable HTTP** transport: * **Endpoint:** `POST /mcp` * **Content-Type:** `application/json` * **Protocol:** JSON-RPC 2.0 * **Methods:** `initialize`, `notifications/initialized`, `tools/list`, `tools/call`, `ping` ## Self-Hosting When self-hosting, your MCP endpoint is your task runner URL + `/mcp`: ``` https://your-task-runner-host:3001/mcp ``` Set `VITE_TASK_RUNNER_URL` in your frontend environment to have the config snippet auto-populate with the correct URL. ## Security Considerations * Only agents explicitly marked as `is_mcp_published = true` are exposed * All requests require a valid Bearer token * Keys are workspace-scoped — one workspace's key cannot access another's agents * Each tool call creates a full task record with audit trail * Rate limiting is inherited from your task runner configuration # Observability Source: https://docs.crewform.tech/observability Trace and debug multi-agent workflows with Langfuse, Datadog, Jaeger, and any OpenTelemetry backend ## Overview CrewForm's task runner supports **opt-in observability** via OpenTelemetry and Langfuse. When enabled, every task execution, LLM call, tool invocation, and team run is traced with span-level detail — giving you full visibility into multi-agent workflows. Tracing is entirely opt-in. If no observability env vars are set, there is zero overhead — no SDK is loaded, no spans are emitted. ## Supported Backends | Backend | Setup | Best For | | ------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------- | | **Langfuse** | `LANGFUSE_PUBLIC_KEY` + `LANGFUSE_SECRET_KEY` | AI-native observability with LLM generation tracking, cost analysis, prompt debugging | | **Datadog** | `OTEL_EXPORTER_OTLP_ENDPOINT` | Enterprise APM with existing Datadog infrastructure | | **Jaeger** | `OTEL_EXPORTER_OTLP_ENDPOINT` | Self-hosted open-source tracing | | **Grafana Tempo** | `OTEL_EXPORTER_OTLP_ENDPOINT` | Grafana stack users | | Any OTLP-compatible | `OTEL_EXPORTER_OTLP_ENDPOINT` | Any backend that accepts OTLP HTTP traces | ## Quick Start ### Langfuse (Recommended for AI Workloads) Set these environment variables on your task runner: ```bash theme={null} LANGFUSE_PUBLIC_KEY=pk-lf-... LANGFUSE_SECRET_KEY=sk-lf-... LANGFUSE_BASE_URL=https://cloud.langfuse.com # or your self-hosted URL ``` That's it. Restart the task runner and traces will appear in your Langfuse dashboard. ### Generic OTLP (Datadog, Jaeger, etc.) ```bash theme={null} OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 # Your OTLP collector OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-token # Optional auth ``` ## What Gets Traced ### Single Task Execution ``` Trace: task.execute ├── Generation: llm.call (model, provider, tokens, cost) ├── Span: mcp.discover (server_count, tool_count) ├── Generation: llm.tool_use_call (if tools enabled) └── attributes: task_id, agent_id, workspace_id ``` ### Team Runs ``` Trace: team.run (team_id, mode) ├── Span: pipeline.execute │ └── (individual task traces nested within) ├── Span: orchestrator.execute │ └── (brain + delegate task traces) └── Span: collaboration.execute └── (turn-by-turn task traces) ``` ### Attributes on Every Trace | Attribute | Description | | ----------------------- | ---------------------------------------------- | | `crewform.workspace_id` | Workspace that owns the task | | `crewform.task_id` | Unique task identifier | | `crewform.agent_id` | Agent executing the task | | `crewform.agent_name` | Agent display name | | `crewform.team_id` | Team ID (for team runs) | | `crewform.team_mode` | `pipeline`, `orchestrator`, or `collaboration` | | `crewform.run_id` | Team run ID | ### LLM Generation Attributes (Langfuse) In Langfuse, LLM calls appear as **Generations** with: | Field | Description | | ------------------ | ----------------------------------------------------- | | `model` | Model identifier (e.g. `gpt-4o`, `claude-3.5-sonnet`) | | `provider` | Provider name (e.g. `openai`, `anthropic`) | | `promptTokens` | Input token count | | `completionTokens` | Output token count | | `totalTokens` | Total token count | | `cost` | Estimated cost in USD | | `input` | First 500 chars of the user prompt | | `output` | First 500 chars of the result | ## Environment Variables Reference | Variable | Required | Description | | ----------------------------- | ------------ | ----------------------------------------------------------- | | `LANGFUSE_PUBLIC_KEY` | For Langfuse | Your Langfuse public key | | `LANGFUSE_SECRET_KEY` | For Langfuse | Your Langfuse secret key | | `LANGFUSE_BASE_URL` | No | Langfuse server URL (default: `https://cloud.langfuse.com`) | | `OTEL_EXPORTER_OTLP_ENDPOINT` | For OTLP | OTLP HTTP collector endpoint (e.g. `http://localhost:4318`) | | `OTEL_EXPORTER_OTLP_HEADERS` | No | Auth headers for OTLP endpoint | ## Docker / Self-Hosted Setup Add the env vars to your task runner service in `docker-compose.yml`: ```yaml theme={null} task-runner: environment: # Langfuse - LANGFUSE_PUBLIC_KEY=pk-lf-... - LANGFUSE_SECRET_KEY=sk-lf-... # Or OTLP # - OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318 ``` For self-hosted Langfuse, you can run it alongside CrewForm in the same Docker Compose stack. See [langfuse.com/docs/deployment/self-host](https://langfuse.com/docs/deployment/self-host) for setup instructions. ## Troubleshooting ### Traces Not Appearing 1. Verify env vars are set on the **task runner** process (not the web app) 2. Check task runner logs for `[Tracing] Langfuse client initialized` or `[Tracing] OTLP exporter initialized` 3. If you see `[Tracing] No observability env vars set`, the vars aren't reaching the process ### High Latency Tracing adds minimal overhead (typically less than 1ms per span). If you notice latency: * Ensure your OTLP collector is network-local to the task runner * Langfuse batches traces automatically — no additional config needed # Orchestration teams Source: https://docs.crewform.tech/orchestration-teams # Orchestration Teams Orchestration is CrewForm's most autonomous team mode. A **brain agent** receives the task, breaks it down, delegates subtasks to **worker agents**, evaluates their outputs, requests revisions when needed, and synthesises a final answer — all without human intervention. ## How It Works ``` User Input │ ▼ ┌──────────────┐ delegate_to_worker() │ Brain Agent │ ──────────────────────────────► Worker A │ (Orchestrator)│ ◄──── result ───────────────── │ │ │ │ delegate_to_worker() │ │ ──────────────────────────────► Worker B │ │ ◄──── result ───────────────── │ │ │ │ [quality < threshold?] │ │ request_revision() │ │ ──────────────────────────────► Worker A │ │ ◄──── revised result ────────── │ │ │ │ final_answer() └──────────────┘ │ ▼ Final Output ``` The brain operates in a **tool-use loop** — it reasons about the task, issues tool calls (delegate, request revision, accept, or finalise), and receives results back. This continues until `final_answer` is called or the loop safety limit (20 iterations) is reached. ## Creating an Orchestration Team 1. Navigate to **Teams → New Team** 2. Give it a name and description 3. Select **Orchestrator** as the team mode 4. Configure the brain and worker agents (see below) ## Configuration ### Brain Agent The brain agent is the orchestrator. It receives the original task and is responsible for the full reasoning loop. Choose a capable, instruction-following model here — Claude Opus or GPT-4o work well. > **Tip:** The brain's system prompt is overridden by CrewForm's orchestrator prompt, which teaches it how to use the delegation tools. The agent's own system prompt is prepended as additional context. ### Worker Agents Workers are the specialists — each receives a focused subtask from the brain and returns a result. You can add as many workers as needed. Each worker's system prompt defines their expertise: ``` You are a senior TypeScript developer specialising in React and performance optimisation. Review the code for bugs, type errors, and performance issues. ``` ### Configuration Fields | Field | Description | Default | | ------------------------ | ----------------------------------------------------------------------------------------- | -------- | | **Brain Agent** | The orchestrator agent that plans and delegates | Required | | **Worker Agents** | One or more specialist agents to delegate to | Min 1 | | **Quality Threshold** | Minimum acceptable quality score (0.0–1.0). Outputs below this trigger a revision request | 0.7 | | **Max Delegation Depth** | Maximum revision rounds per delegation before the brain must accept or skip | 3 | | **Routing Strategy** | How the brain selects workers — currently `auto` (brain decides freely) | `auto` | | **Planner Enabled** | Reserved for future structured planning step (currently unused) | false | ## Brain Agent Tools The brain agent has four tools available during its reasoning loop: ### `delegate_to_worker` Sends a subtask to a specific worker agent. ```json theme={null} { "tool": "delegate_to_worker", "arguments": { "agent_id": "", "instruction": "Analyse the performance bottlenecks in the provided React component and suggest optimisations." } } ``` ### `request_revision` Asks a worker to revise their previous output, with specific feedback. ```json theme={null} { "tool": "request_revision", "arguments": { "delegation_id": "", "feedback": "The analysis is too generic. Focus specifically on unnecessary re-renders and memo opportunities." } } ``` ### `accept_result` Marks a delegation as accepted — no further revision needed. ```json theme={null} { "tool": "accept_result", "arguments": { "delegation_id": "" } } ``` ### `final_answer` Submits the synthesised final output. The run completes immediately when this is called. ```json theme={null} { "tool": "final_answer", "arguments": { "output": "## Code Review Summary\n\n### Critical Issues\n..." } } ``` ## Delegation Lifecycle Each delegation follows this lifecycle: ``` pending → running → completed │ [quality check] │ ┌── pass ────┴──── fail ──┐ │ │ accepted revision_requested │ running (retry) │ completed (or failed) ``` You can monitor the delegation tree in real-time on the run detail page — each delegation shows its status, worker output, and revision history. ## Team Memory Orchestration teams have **persistent memory** across runs. After each completed run, the output is stored as a memory entry. On subsequent runs, relevant past memories are automatically retrieved and injected into the brain's system prompt. This means your team improves over time — the brain learns from previous orchestrations on similar tasks. Memory is scoped to the team — each team has its own memory store that doesn't bleed into other teams. ## Example: Multi-Step Research Report A three-worker orchestration team for producing research reports: **Brain Agent** — Claude Opus * System prompt: "You are a research director. Break complex research tasks into focused subtasks and synthesise professional reports." **Workers:** 1. **Ava (Researcher)** — "Search and gather factual information, statistics, and expert sources on the given topic." 2. **Sam (Writer)** — "Transform research notes into clear, structured prose. Use professional tone and logical flow." 3. **Smith (Editor)** — "Review and polish written content. Fix grammar, improve clarity, ensure factual accuracy." **Workflow:** 1. Brain delegates "Research: AI adoption in healthcare 2025" → Ava 2. Brain delegates "Write a 1500-word report from these notes" + Ava's output → Sam 3. Brain evaluates Sam's draft — requests revision if below quality threshold 4. Brain delegates "Final editorial review" → Smith 5. Brain calls `final_answer` with synthesised report ## Visual Workflow Builder (Canvas) Orchestration teams include a **Visual Workflow Builder** — an interactive canvas for designing and monitoring your brain + worker graph in real-time. See the full [Visual Workflow Builder Guide](./visual-workflow-builder.md) for complete documentation. ### Canvas Features * **Drag agents** from the sidebar onto the canvas to add them as workers * **Connect nodes** by dragging edges to define delegation relationships * **Right-click context menu** — Delete, Auto-layout, Set as Brain, Fit View * **Glassmorphism styling** — frosted glass nodes with hover lift effects * **Searchable sidebar** — filter agents by name or model ### Live Execution Visualization During a team run, the canvas shows live execution state on each node: * **Node states** — Idle, Running (blue pulse), Completed (green ✓), Failed (red ✕) * **Camera auto-follow** — Canvas pans to the currently executing agent * **Execution timeline** — Step-by-step progress rail with clickable steps * **Transcript panel** (`T`) — Real-time brain-to-worker message feed with delegation/result filters * **Tool heatmap** — Tool usage stats with success rates ### Keyboard Shortcuts Press `?` for the full shortcuts overlay. Key shortcuts: `F` (fit view), `L` (auto-layout), `T` (transcript), `⌘Z` (undo), `⌘A` (select all). ### Auto-Layout Click **Auto-Layout** or press `L` for a **top-to-bottom** layout — brain at the top, workers fanning out below. ### Position Persistence Node positions are saved automatically and restored when you revisit — stored in `teams.config` JSONB column. ## Monitoring The run detail page shows the full delegation tree: * **Delegations panel** — each delegation with status, worker name, instruction, output, and revision count * **Messages feed** — real-time log of brain decisions and worker responses * **Token usage** — per-delegation breakdown * **Delegation depth** — current iteration count in the orchestrator loop ## Tips * **Brain model matters.** The brain needs to reliably output JSON tool calls. Claude Sonnet 4+ and GPT-4o handle this well. Smaller or older models may produce malformed tool calls. * **Specific worker prompts = better delegation.** The brain picks workers based on their name and description. Clear, focused descriptions (e.g. "TypeScript code reviewer" vs "AI assistant") lead to better routing. * **Set quality threshold thoughtfully.** Too high (0.9+) and the brain will loop excessively. Too low (0.3) and poor outputs get accepted. 0.6–0.8 is a good starting range. * **Watch delegation depth.** If runs are looping on revisions, consider increasing `max_delegation_depth` or lowering the quality threshold, or improving the worker's system prompt. * **Use team memory.** After a few runs on similar tasks, team memory kicks in and the brain starts with better context. ## Related * [Pipeline Teams](./pipeline-teams.md) — Fixed sequential steps, no dynamic routing * [Collaboration Teams](./collaboration-teams.md) — Agents discuss and reach consensus # Output routes Source: https://docs.crewform.tech/output-routes # Output Routes Output routes deliver agent and team run results to external destinations when a task completes or fails. Each route listens for specific events and posts a structured payload to its configured destination. Supported destinations: | Type | How it delivers | | ----------------------------------- | ------------------------------------------------------------ | | [HTTP Webhook](#http-webhook) | POST to any URL with HMAC-SHA256 signing | | [Slack](#slack) | Incoming Webhook — formatted message with result block | | [Discord](#discord) | Discord Webhook — embedded message with result | | [Telegram](#telegram) | Bot API — sends message to a chat or group | | [Microsoft Teams](#microsoft-teams) | Incoming Webhook — Adaptive Card | | [Asana](#asana) | Creates a task in a project via Personal Access Token | | [Trello](#trello) | Creates or updates a card on a board via API Key + Token | | [Notion](#notion) | Creates a page in a database via Integration Token | | [GitHub Issues](#github-issues) | Creates an issue in a repository via Personal Access Token | | [Email (Resend)](#email-resend) | Sends HTML email via Resend API | | [SMTP Email](#smtp-email) | Sends email via custom SMTP server (nodemailer) | | [Linear](#linear) | Creates an issue via GraphQL API with team label resolution | | [Google Sheets](#google-sheets) | Appends rows to a spreadsheet via OAuth 2.0 | | [Gmail](#gmail) | Sends email from your connected Google account via OAuth 2.0 | | [Google Docs](#google-docs) | Creates a document in Google Drive via OAuth 2.0 | | [Google Calendar](#google-calendar) | Creates a review event via OAuth 2.0 | *** ## Concepts ### Events Every route subscribes to one or more events. Only matching events trigger delivery: | Event | Fires when | | -------------------- | ------------------------------------------------------------ | | `task.completed` | An agent task finishes successfully | | `task.failed` | An agent task errors out | | `team_run.completed` | A pipeline, orchestrator, or collaboration team run finishes | | `team_run.failed` | A team run errors out | ### Payload Every route receives the same JSON payload: ```json theme={null} { "event": "task.completed", "task_id": "uuid-or-null", "team_run_id": "uuid-or-null", "task_title": "Summarise Q4 earnings report", "agent_name": "Research Analyst", "status": "completed", "result_preview": "First 500 chars of the result...", "result_full": "Full result text...", "error": null, "timestamp": "2026-03-06T18:00:00.000Z", "attachments": [ { "name": "report.pdf", "type": "application/pdf", "size": 204800, "url": "https://... (signed, expires in 24h)", "direction": "input" } ] } ``` * `result_full` — the complete output. Some destinations (Slack, Discord, Telegram, Teams) truncate long outputs in the formatted message; use HTTP if you need the full untruncated result. * `attachments` — file attachments associated with the task or team run. Signed download URLs expire after 24 hours. * `task_id` or `team_run_id` — only one will be set, depending on whether the event is from an agent task or a team run. ### Retry Each delivery is attempted up to **2 times** (initial + 1 retry after 5 seconds). Failed deliveries are logged in **Settings → Output Routes → Logs** with the HTTP status code and error message. ### Scoping Deliveries By default, all active routes in a workspace receive all matching events. You can restrict an agent or team to only send to specific routes — see the [Output Routes selector in Agents](./agents.md#output-routes) and [Pipeline Teams](./pipeline-teams.md#output-routes). *** ## Creating a Route 1. Go to **Settings → Output Routes** 2. Click **New Route** 3. Choose the destination type and configure it 4. Select which events to subscribe to 5. Save — optionally test with the **Send Test** button *** ## HTTP Webhook The most flexible option. CrewForm POSTs the full JSON payload to your URL. Use this for custom integrations, internal tooling, or platforms not natively supported. ### Configuration | Field | Required | Description | | ---------- | -------- | --------------------------------------------------- | | **URL** | ✅ | HTTPS endpoint to POST to | | **Secret** | Optional | If set, CrewForm signs the payload with HMAC-SHA256 | ### Signature Verification If you set a secret, CrewForm adds a `X-CrewForm-Signature` header to every request: ``` X-CrewForm-Signature: sha256= ``` The signature is computed as `HMAC-SHA256(secret, raw-body)`. Verify it on your server: ```javascript theme={null} // Node.js example const crypto = require('crypto'); function verifyCrewFormSignature(rawBody, secret, signatureHeader) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signatureHeader), Buffer.from(expected) ); } ``` ```python theme={null} # Python example import hmac, hashlib def verify_signature(raw_body: bytes, secret: str, header: str) -> bool: expected = 'sha256=' + hmac.new( secret.encode(), raw_body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, header) ``` ### Example Handler (Express) ```javascript theme={null} app.post('/crewform-webhook', express.raw({ type: 'application/json' }), (req, res) => { const sig = req.headers['x-crewform-signature']; if (!verifyCrewFormSignature(req.body, process.env.CREWFORM_SECRET, sig)) { return res.status(401).send('Invalid signature'); } const payload = JSON.parse(req.body); console.log(`Event: ${payload.event}, Task: ${payload.task_title}`); console.log(`Result: ${payload.result_full}`); res.sendStatus(200); }); ``` > **Tip:** CrewForm treats any 2xx response as success. Return 200 quickly and process async to avoid timeouts. *** ## Slack Posts a formatted message to a Slack channel via an Incoming Webhook. Results appear in a coloured attachment block — green for completed, red for failed. ### Setup 1. Go to [api.slack.com/apps](https://api.slack.com/apps) → **Create New App → From Scratch** 2. Go to **Incoming Webhooks** → Enable → **Add New Webhook to Workspace** 3. Select the channel and click **Allow** 4. Copy the **Webhook URL** (starts with `https://hooks.slack.com/...`) ### Configuration | Field | Required | Description | | --------------- | -------- | -------------------------- | | **Webhook URL** | ✅ | Slack Incoming Webhook URL | ### Message Format Messages are posted as Block Kit attachments: ```` ✅ Task completed: Summarise Q4 earnings report Agent: Research Analyst ```result output here``` ```` > **Truncation:** Results over 2,900 characters are truncated in the Slack message. Full output is always available in the HTTP webhook payload. *** ## Discord Posts an embedded message to a Discord channel via a Discord Webhook. ### Setup 1. In Discord, open the channel settings → **Integrations → Webhooks** 2. Click **New Webhook** → give it a name 3. Copy the **Webhook URL** ### Configuration | Field | Required | Description | | --------------- | -------- | ------------------- | | **Webhook URL** | ✅ | Discord Webhook URL | ### Message Format Results appear as Discord embeds — green border for completed, red for failed — with agent name, task title, status, and result inline. > **Truncation:** Results over 1,000 characters are truncated in the Discord embed. Use HTTP webhook if you need full output. > **Note:** This is a one-way **output route** (CrewForm → Discord). For two-way integration where Discord users can trigger agents via `/ask`, see the [Discord Integration guide](./discord-integration.md). *** ## Telegram Sends a message to a Telegram chat or group via the Bot API. ### Setup 1. Create a bot via [@BotFather](https://t.me/BotFather) → `/newbot` 2. Copy the **Bot Token** (format: `123456789:AABBcc...`) 3. Get the **Chat ID** of the target chat: * For personal chats: message the bot, then visit `https://api.telegram.org/bot/getUpdates` and find `chat.id` * For groups: add the bot to the group, send a message, check `getUpdates` * For channels: add the bot as admin, use the channel's `@username` as the chat ID (e.g. `@mycrewformchannel`) or the numeric ID (e.g. `-1001234567890`) ### Configuration | Field | Required | Description | | ------------- | -------- | ------------------------------------------------ | | **Bot Token** | ✅ | Token from @BotFather | | **Chat ID** | ✅ | Numeric chat ID, group ID, or `@channelusername` | ### Message Format ```` ✅ Task completed Title: Summarise Q4 earnings report Agent: Research Analyst ```result output here``` ```` > **Truncation:** Results over 3,500 characters are truncated in the Telegram message. > **Note:** This is a one-way **output route** (CrewForm → Telegram). For two-way integration where Telegram users can trigger agents, see the [Telegram Channel guide](./channels.md#telegram). *** ## Microsoft Teams Posts an Adaptive Card to a Teams channel via an Incoming Webhook. Cards render with a colour-coded header, fact set, and result body. ### Setup 1. In Teams, open the channel → **Connectors** (⋯ menu → Connectors) 2. Find **Incoming Webhook** → **Configure** 3. Give it a name and upload an icon (optional) 4. Click **Create** and copy the **Webhook URL** > **Modern Teams:** Microsoft is migrating from Connectors to **Workflows**. If Connectors aren't available in your tenant, use the Power Automate Workflows app instead: add the "Post to a channel when a webhook request is received" workflow and copy its URL. ### Configuration | Field | Required | Description | | --------------- | -------- | ----------------------------------------------------------- | | **Webhook URL** | ✅ | Teams Incoming Webhook URL (or Power Automate Workflow URL) | ### Message Format Delivered as an Adaptive Card (version 1.4): * **Header:** ✅ / ❌ with task/team run status * **Fact Set:** Prompt/Task, Agent/Team, Status * **Body:** Result text (monospace font) * **Error:** Shown if the task failed > **Truncation:** Results over 2,000 characters are truncated in the Teams card. *** ## Asana Creates a new task in an Asana project when a CrewForm task or team run completes or fails. ### Setup 1. Go to [app.asana.com/0/my-apps](https://app.asana.com/0/my-apps) → **Create New Token** (Personal Access Token) 2. Copy the **PAT** 3. Find your **Project GID**: * Open the project in Asana * The URL contains the GID: `https://app.asana.com/0//...` * Or use the Asana API: `GET https://app.asana.com/api/1.0/projects` ### Configuration | Field | Required | Description | | ------------------------- | -------- | ------------------------------------- | | **Personal Access Token** | ✅ | Asana PAT from your account settings | | **Project GID** | ✅ | Numeric project ID from the Asana URL | ### Task Format Each delivery creates an Asana task with: * **Name:** `[CrewForm] ` * **Notes:** Event type, task/agent details, timestamp, and full result > **Tip:** Use Asana rules to automatically assign, tag, or move created tasks to specific sections based on their name or status. *** ## Trello Creates a new card (or updates an existing one) on a Trello board when a CrewForm task or team run completes or fails. Trello also supports **bidirectional integration** — cards moved to a trigger list can start agent tasks, and results are posted back as comments. ### Setup 1. Go to [trello.com/power-ups/admin](https://trello.com/power-ups/admin) → create or select a Power-Up to get your **API Key** 2. From the API key page, click the **Token** link to generate a token with read/write access 3. Find your **Board ID**: * Open the board in Trello * The URL contains the ID: `https://trello.com/b//...` 4. Find the **List ID** for the target list: * Use the Trello API: `GET https://api.trello.com/1/boards//lists?key=&token=` * Or use a browser extension like [Trello Card Numbers](https://chrome.google.com/webstore/detail/trello-card-numbers) 5. *(Optional)* Find a **Review List ID** — completed cards will be moved here automatically ### Configuration | Field | Required | Description | | ------------------- | -------- | ----------------------------------------------------- | | **API Key** | ✅ | Trello API key from the Power-Up admin page | | **Token** | ✅ | Trello token with read/write access | | **Board ID** | ✅ | Board short ID from the Trello URL | | **Default List ID** | ✅ | List where new result cards are created | | **Review List ID** | Optional | If set, cards are moved here after results are posted | ### Card Format Each delivery creates a Trello card with: * **Name:** `[CrewForm] ` * **Description:** Event type, task/agent details, timestamp, and full result If a card mapping already exists (from an inbound Trello trigger), the result is posted as a **comment** on the existing card instead of creating a new one, and the card is moved to the Review list. ### Bidirectional Flow When used with a [Trello Messaging Channel](./channels.md#trello), CrewForm supports a full round-trip: 1. **Inbound:** A card is created or moved to the trigger list → CrewForm creates a task 2. **Agent processes** the card's title/description as the prompt 3. **Outbound:** The agent result is posted as a comment on the original card → card moves to the Review list > **Tip:** Set up two lists on your board — an "AI Work" list (trigger) and a "Review" list (review) — for a clean Kanban workflow with your AI agents. *** ## Delivery Logs Every delivery attempt is logged. View logs in **Settings → Output Routes → \[Route Name] → Logs**: | Column | Description | | --------- | ---------------------------------- | | Timestamp | When delivery was attempted | | Event | Which event triggered the delivery | | Status | `success` or `failed` | | HTTP Code | Response code from the destination | | Error | Error message if delivery failed | Logs are retained for 30 days. *** ## Self-Hosted Environment Variables If you self-host CrewForm, no extra environment variables are needed for output routes — all credentials are stored in the database per-route. The task runner reads them at delivery time. See the [Self-Hosting Guide](./self-hosting.md) for general environment setup. *** ## Notion Creates a new page in a Notion database when a CrewForm task or team run completes or fails. ### Setup 1. Go to [notion.so/my-integrations](https://www.notion.so/my-integrations) → **New Integration** 2. Give it a name (e.g. "CrewForm") and select your workspace 3. Copy the **Internal Integration Token** (starts with `ntn_...`) 4. In Notion, open the target database → **⋯ → Connections → Add connection** → select your integration ### Configuration | Field | Required | Description | | --------------------- | -------- | --------------------------------------------------------- | | **Integration Token** | ✅ | Notion Internal Integration Token | | **Database ID** | ✅ | ID from the database URL: `notion.so/?v=...` | ### Page Format Each delivery creates a Notion page with: * **Title:** `[CrewForm] ` * **Content:** Event type, agent details, timestamp, and full result as text blocks *** ## GitHub Issues Creates an issue in a GitHub repository when a CrewForm task or team run completes or fails. ### Setup 1. Go to [github.com/settings/tokens](https://github.com/settings/tokens) → **Generate new token (classic)** 2. Select the `repo` scope 3. Copy the **Personal Access Token** ### Configuration | Field | Required | Description | | ------------------------- | -------- | ---------------------------------------------------------- | | **Personal Access Token** | ✅ | GitHub PAT with `repo` scope | | **Repository** | ✅ | Format: `owner/repo` (e.g. `CrewForm/crewform`) | | **Labels** | Optional | Comma-separated labels to apply (e.g. `ai-output, review`) | | **Assignees** | Optional | Comma-separated GitHub usernames to assign | ### Issue Format * **Title:** `[CrewForm] ` * **Body:** Event type, agent details, timestamp, and full result in Markdown *** ## Email (Resend) Sends a styled HTML email via the [Resend](https://resend.com) API. Ideal for managed email delivery without configuring an SMTP server. ### Setup 1. Sign up at [resend.com](https://resend.com) and verify a sending domain 2. Go to **API Keys** → create a new key 3. Copy the **API Key** ### Configuration | Field | Required | Description | | -------------------- | -------- | ------------------------------------------------------------ | | **API Key** | ✅ | Resend API key | | **From Email** | ✅ | Verified sender address (e.g. `alerts@yourdomain.com`) | | **To Email(s)** | ✅ | Comma-separated recipient addresses | | **Subject Template** | Optional | Supports `{{title}}`, `{{status}}`, `{{agent}}` placeholders | *** ## SMTP Email Sends email via any SMTP server using [nodemailer](https://nodemailer.com). Use this for self-hosted email or providers like Gmail SMTP, SendGrid, Mailgun, etc. ### Configuration | Field | Required | Description | | -------------------- | -------- | ------------------------------------------------------------ | | **SMTP Host** | ✅ | SMTP server hostname (e.g. `smtp.gmail.com`) | | **SMTP Port** | ✅ | Port number (typically `587` for TLS, `465` for SSL) | | **Username** | ✅ | SMTP authentication username | | **Password** | ✅ | SMTP authentication password or app password | | **From Email** | ✅ | Sender email address | | **To Email(s)** | ✅ | Comma-separated recipient addresses | | **Subject Template** | Optional | Supports `{{title}}`, `{{status}}`, `{{agent}}` placeholders | > **Gmail SMTP:** Use an App Password (not your regular password). Go to Google Account → Security → 2-Step Verification → App passwords. *** ## Linear Creates an issue in Linear when a CrewForm task or team run completes or fails. Uses the Linear GraphQL API. ### Setup 1. Go to [linear.app/settings/api](https://linear.app/settings/api) → **Personal API keys** → create a key 2. Copy the **API Key** 3. Find your **Team Key** (the short prefix like `ENG`, `OPS` visible in issue IDs) ### Configuration | Field | Required | Description | | ------------ | -------- | ------------------------------------------------------------------ | | **API Key** | ✅ | Linear Personal API key | | **Team Key** | ✅ | Team identifier (e.g. `ENG`) | | **Labels** | Optional | Comma-separated label names (matched against existing team labels) | ### Issue Format * **Title:** `[CrewForm] ` * **Description:** Full result in Markdown with agent and event metadata *** ## Google Workspace Google destinations use **OAuth 2.0** — you connect your Google account once per workspace, and CrewForm handles token refresh automatically. ### Setup (One-Time) 1. When creating a Google output route, click **Connect Google** in the configuration form 2. Sign in with your Google account and grant the requested permissions 3. CrewForm stores encrypted OAuth tokens — no API keys needed > **Self-Hosted:** You must configure a Google Cloud project with OAuth credentials. Set `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` on both Supabase Edge Functions and the task runner. See the [Self-Hosting Guide](./self-hosting.md) for details. ### Google Sheets Appends task results as new rows in a Google Spreadsheet. | Field | Required | Description | | ------------------ | -------- | ----------------------------------------------------------------------- | | **Spreadsheet ID** | ✅ | ID from the spreadsheet URL: `docs.google.com/spreadsheets/d//edit` | | **Sheet Name** | Optional | Target sheet tab (defaults to first sheet) | Each delivery appends a row with: Timestamp, Event, Task Title, Agent, Status, Result. ### Gmail Sends an email from your connected Google account. | Field | Required | Description | | -------------------- | -------- | ------------------------------------------------------------ | | **To Email(s)** | ✅ | Comma-separated recipient addresses | | **Subject Template** | Optional | Supports `{{title}}`, `{{status}}`, `{{agent}}` placeholders | Emails are sent as the authenticated Google user with a styled HTML template. ### Google Docs Creates a new Google Document with the full agent output. | Field | Required | Description | | ------------------- | -------- | -------------------------------------------------------------------------------- | | **Drive Folder ID** | Optional | Target folder from URL: `drive.google.com/drive/folders/`. Defaults to root. | Each delivery creates a document named `[CrewForm] ` with the full result. ### Google Calendar Creates a review event on your Google Calendar. | Field | Required | Description | | ---------------------- | -------- | ----------------------------------------------------------------------- | | **Calendar ID** | Optional | Defaults to `primary`. Use a specific calendar ID for custom calendars. | | **Duration (minutes)** | Optional | Event duration in minutes (default: 30) | Events are scheduled 1 hour after task completion with the task title and result in the description. # Pipeline teams Source: https://docs.crewform.tech/pipeline-teams # Pipeline Teams Guide > **CrewForm has three team modes.** Choose the right one for your workflow: > > | Mode | How it works | Best for | > | ----------------------------------------- | ----------------------------------------------------------- | ------------------------------------------ | > | **Pipeline** ← you are here | Fixed sequential steps — each agent's output feeds the next | Structured multi-step workflows | > | [Orchestration](./orchestration-teams.md) | A brain agent dynamically delegates to workers | Autonomous, adaptive task execution | > | [Collaboration](./collaboration-teams.md) | Agents take turns in a shared discussion | Brainstorming, reviews, consensus-building | Pipeline teams let you chain multiple agents together, where each agent's output feeds into the next. This is ideal for multi-step workflows like research → analysis → report generation. ## How Pipelines Work ``` Input → Agent A → Agent B → Agent C → Final Output (step 1) (step 2) (step 3) ``` Each step receives: * The **original task input** * The **previous step's output** (if not the first step) * Its own **step instructions** and **expected output format** ## Creating a Pipeline Team 1. Navigate to **Teams → New Team** 2. Give it a name and description 3. Select **Pipeline** as the team mode 4. Add steps in order — each step maps to an agent ### Step Configuration | Field | Description | | ------------------- | ------------------------------------------------------ | | **Agent** | Which agent executes this step | | **Step Name** | Label for this step (e.g., "Research") | | **Instructions** | What this specific step should do | | **Expected Output** | Format the agent should respond in | | **On Failure** | `retry` (up to max), `stop` (halt pipeline), or `skip` | | **Max Retries** | How many times to retry on failure (0–5) | ## Example: Content Pipeline A three-step pipeline for generating blog posts: ### Step 1: Research Agent * **Agent**: Research Specialist (Claude Sonnet) * **Instructions**: "Research the given topic. Find 5 key facts, statistics, and expert quotes." * **Expected Output**: "Bullet-point list of findings with sources" * **On Failure**: retry (max 2) ### Step 2: Writer Agent * **Agent**: Content Writer (GPT-4o) * **Instructions**: "Using the research provided, write a 1000-word blog post. Use an engaging, professional tone." * **Expected Output**: "Markdown-formatted blog post with headers" * **On Failure**: retry (max 1) ### Step 3: Editor Agent * **Agent**: Copy Editor (Claude Haiku) * **Instructions**: "Review and polish the blog post. Fix grammar, improve flow, ensure factual accuracy against the research." * **Expected Output**: "Final polished blog post in Markdown" * **On Failure**: stop ## Running a Pipeline 1. Go to the team detail page 2. Click **Run Pipeline** 3. Enter the task input (e.g., "Write a blog post about AI in healthcare") 4. Watch each step execute in real-time The run detail page shows: * Overall pipeline status * Per-step status and output * Token usage per step * Total execution time ## Pipeline Context Each step automatically receives context about its position: ``` ## Task [Original input from the user] ## Previous Step Output [Output from the previous step] ## Your Instructions [Step-specific instructions] ## Expected Output Format [What format to respond in] ## Pipeline Context This is step 3 in a multi-step pipeline. 2 previous steps have completed. ``` ## Failure Handling | Strategy | Behavior | | --------- | ------------------------------------------------------------------------------------------------------------------- | | **Retry** | Re-runs the step (up to max retries). Useful for transient API errors. | | **Stop** | Halts the entire pipeline. The run is marked as failed. | | **Skip** | Marks the step as skipped and continues to the next step. The next step won't receive output from the skipped step. | ## Fan-Out (Parallel Branching) Pipeline teams support **fan-out steps** — a single step that dispatches work to multiple agents in parallel, then merges the results. ``` Input → Agent A → [Fan-Out] → Agent B ─┐ → Agent C ─┤→ Merge Agent D → Agent E → Output → Agent D ─┘ (parallel branches) (merge) ``` ### Creating a Fan-Out Step 1. In the pipeline step list, click **+ Add Fan-Out Step** 2. Select **Parallel Agents** — the agents that will run concurrently 3. Select a **Merge Agent** — the agent that receives all branch results and synthesizes them 4. Configure **Merge Instructions** — how the merge agent should combine the outputs 5. Choose a **Failure Mode** — what happens if a branch fails ### Fan-Out Step Configuration | Field | Description | | ---------------------- | ------------------------------------------------------------------------------------ | | **Parallel Agents** | 2+ agents that execute concurrently on the same input | | **Merge Agent** | Single agent that receives all branch outputs and produces a unified result | | **Merge Instructions** | Specific instructions for the merge agent on how to combine results | | **On Branch Failure** | `fail_fast` (stop all branches), `continue` (complete remaining branches), or `skip` | ### Failure Modes | Mode | Behavior | | ------------- | --------------------------------------------------------------------------- | | **Fail Fast** | If any branch fails, cancel remaining branches and fail the step | | **Continue** | Complete all remaining branches; pass successful results to the merge agent | | **Skip** | Skip the entire fan-out step; proceed to the next pipeline step | ### Canvas Visualization On the visual workflow canvas, fan-out steps render as a **branching pattern**: * A **fan-out node** splits into parallel branch edges * Each **branch agent** appears as a separate node * Branches converge at a **merge node** * During execution, each branch shows its individual status (running/completed/failed) ### Example: Multi-Perspective Analysis A fan-out step for analyzing a business proposal from multiple angles: **Parallel Agents:** * Financial Analyst → evaluates ROI and risk * Technical Reviewer → assesses feasibility * Market Researcher → checks competitive landscape **Merge Agent:** Strategy lead synthesizes all three perspectives into a recommendation. ### Pipeline Context for Merge Agents The merge agent receives a special context block: ``` ## Fan-Out Branch Results ### Branch 1: Financial Analyst [Financial analysis output] ### Branch 2: Technical Reviewer [Technical assessment output] ### Branch 3: Market Researcher [Market research output] ## Merge Instructions Synthesize all branch results into a single strategic recommendation. ``` ## Best Practices 1. **Start simple** — Begin with 2-3 steps and add complexity gradually 2. **Specialized agents** — Each agent should do one thing well 3. **Clear handoffs** — Define expected output format so the next step knows what to expect 4. **Use retry for API steps** — LLM APIs can have transient failures 5. **Use stop for critical steps** — If step 1 fails, there's no point running step 2 6. **Monitor costs** — Each step uses tokens; longer pipelines cost more ## Visual Workflow Builder (Canvas) Pipeline teams include a **Visual Workflow Builder** — an interactive canvas for designing, managing, and monitoring your pipeline graph in real-time. See the full [Visual Workflow Builder Guide](./visual-workflow-builder.md) for complete documentation. ### Canvas Features * **Drag agents** from the sidebar onto the canvas to add them as steps * **Connect nodes** by dragging edges to define execution order * **Delete nodes** via right-click context menu or keyboard shortcut * **Drag to rearrange** — reposition nodes freely; positions are saved automatically * **Glassmorphism styling** — frosted glass nodes with hover lift effects * **Searchable sidebar** — filter agents by name or model when you have many agents ### Live Execution Visualization During a team run, the canvas transforms into a live monitoring dashboard: * **Node states** — Idle (default), Running (blue pulse), Completed (green ✓), Failed (red ✕) * **Camera auto-follow** — Canvas pans smoothly to the currently executing agent * **Execution timeline** — Horizontal progress rail showing step-by-step status * **Animated edges** — Flowing dashed edges indicate data flow direction ### Observability Panels * **Transcript** (`T`) — Real-time message feed with filter buttons and tool call expansion * **Tool Heatmap** — Aggregated tool usage with success rates and latency stats ### Keyboard Shortcuts | Shortcut | Action | | ------------------------ | ----------------------- | | `⌘ Z` / `Ctrl+Z` | Undo | | `⌘ ⇧ Z` / `Ctrl+Shift+Z` | Redo | | `⌘ A` / `Ctrl+A` | Select all | | `F` | Fit view | | `L` | Auto-layout | | `T` | Toggle transcript | | `?` | Keyboard shortcuts help | | `Escape` | Close panels / deselect | ### Auto-Layout Click the **Auto-Layout** button or press `L` to automatically arrange your nodes using the [dagre](https://github.com/dagrejs/dagre) layout algorithm. Pipeline teams use a **top-to-bottom** layout for clear sequential flow. ### Position Persistence Node positions are saved as part of the team configuration. When you reload the page or revisit the team, your canvas layout is exactly as you left it. No database migration is needed — positions are stored in the existing `teams.config` JSONB column. ## Output Routes Like individual agents, pipeline teams support targeted output delivery. By default, team run results are broadcast to all active output routes. To restrict where a team's output is sent: 1. Open **Teams → \[Team Name] → Settings** 2. Scroll to **Output Routes** 3. Select one or more specific channels — or leave blank to send to all This setting applies to the final pipeline result. Individual step outputs are internal and not broadcast. ## Monitoring View pipeline metrics on the **Analytics** page: * Total tasks completed per team * Average execution time * Token usage breakdown by step * Cost per pipeline run ## Related * [Orchestration Teams](./orchestration-teams.md) — Brain agent dynamically delegates to workers * [Collaboration Teams](./collaboration-teams.md) — Agents discuss and reach consensus # Quickstart Source: https://docs.crewform.tech/quickstart # Quick Start Guide Get CrewForm running locally in under 5 minutes. Want the fastest product tour after setup? Follow [Run Your First Agent System](/first-agent-system) to activate the Research Brief demo and run a real multi-agent pipeline. ## Prerequisites * **Node.js** 20+ * **npm** 10+ * **Supabase** account (free tier works) — [supabase.com](https://supabase.com) * At least one LLM API key (Anthropic, Google, or OpenAI) ## 1. Clone & Install ```bash theme={null} git clone https://github.com/CrewForm/crewform.git cd crewform npm install ``` ## 2. Supabase Setup 1. Create a new project at [supabase.com/dashboard](https://supabase.com/dashboard) 2. Go to **Settings → API** and copy your **URL** and **anon key** 3. Go to **SQL Editor** and run each migration file in order: ```bash theme={null} # Files are in supabase/migrations/, run them in numeric order: # 001_initial_schema.sql # 002_rls_policies.sql # ... through to the latest ``` ## 3. Environment ```bash theme={null} cp .env.example .env.local ``` Edit `.env.local` with your values: ```env theme={null} VITE_SUPABASE_URL=https://your-project.supabase.co VITE_SUPABASE_ANON_KEY=your-anon-key VITE_APP_URL=http://localhost:5173 VITE_ENCRYPTION_KEY=generate-a-32-byte-hex-key ``` > **Generate an encryption key:** `openssl rand -hex 32` ## 4. Start Development ```bash theme={null} npm run dev ``` Visit [http://localhost:5173](http://localhost:5173) and sign up for an account. ## 5. Task Runner (for AI execution) The task runner processes agent tasks. In a separate terminal: ```bash theme={null} cd task-runner npm install cp .env.example .env # Add your LLM API keys to .env npm start ``` ## 6. Add Your First Agent 1. Navigate to **Agents → New Agent** 2. Give it a name and description 3. Select a model (e.g., `claude-sonnet-4-20250514`) 4. Write a system prompt 5. Go to **Settings → API Keys** and add your provider key 6. Create a task from the **Tasks** page to test it ## What's Next? * [Agents Guide](./agents.md) — Deep dive into agent configuration * [Pipeline Teams](./pipeline-teams.md) — Sequential multi-agent workflows * [Orchestration Teams](./orchestration-teams.md) — Brain agent delegates to workers dynamically * [Collaboration Teams](./collaboration-teams.md) — Agents discuss and reach consensus * [Channels](./channels.md) — Inbound messaging (Telegram, Slack, Discord, Email) * [Output Routes](./output-routes.md) — Push results to HTTP, Slack, Discord, Telegram, Teams, Asana, Trello * [Discord Integration](./discord-integration.md) — Detailed Discord setup guide * [API Reference](./api-reference.md) — REST API documentation * [Self-Hosting Guide](./self-hosting.md) — Docker production deployment # Self hosting Source: https://docs.crewform.tech/self-hosting # Self-Hosting CrewForm Run CrewForm on your own infrastructure with Docker Compose. This guide covers a **single-server deployment** suitable for teams and small organizations. ## Prerequisites * **Docker** ≥ 24.0 and **Docker Compose** ≥ 2.20 * **2 GB RAM** minimum (4 GB recommended) * **10 GB disk** for database + assets * A **Supabase project** (hosted) or PostgreSQL 15+ (direct mode) ## Quick Start ```bash theme={null} # 1. Clone the repository git clone https://github.com/CrewForm/crewform.git cd crewform # 2. Configure environment cp .env.example .env # Edit .env — at minimum set POSTGRES_PASSWORD # 3. Start all services docker compose up -d # 4. Check status docker compose ps ``` The frontend will be available at **[http://localhost:3000](http://localhost:3000)**. ## Architecture ``` ┌─────────────────────────────────────────────────────┐ │ Docker Compose │ │ │ │ ┌────────────┐ ┌──────────┐ ┌────────────────┐ │ │ │ postgres │ │ migrate │ │ task-runner │ │ │ │ (PG 15) │←─│ (17 SQL) │ │ (Node + tsx) │ │ │ │ :5432 │ │ one-shot │ │ polling loop │ │ │ └────────────┘ └──────────┘ └───────┬────────┘ │ │ │ │ │ │ └──────────┬───────────────────┘ │ │ │ │ │ ┌─────────────────▼───────────────────────────┐ │ │ │ frontend (nginx) │ │ │ │ Vite build → :3000 │ │ │ └──────────────────────────────────────────────┘ │ └───────────────────────┬─────────────────────────────┘ │ (optional) ┌───────▼────────┐ │ Ollama │ │ :11434 (local) │ │ Local LLMs │ └────────────────┘ ``` ## Services | Service | Image | Purpose | Port | | ------------- | ------------------ | --------------------------------- | ---- | | `postgres` | postgres:15-alpine | Database with persistent volume | 5432 | | `migrate` | postgres:15-alpine | Runs SQL migrations, then exits | — | | `frontend` | nginx:1.27-alpine | Serves Vite build (SPA routing) | 3000 | | `task-runner` | node:20-alpine | AI task execution polling service | — | ## Configuration ### Required Variables | Variable | Description | | --------------------------- | -------------------------------------------------------------------------------- | | `POSTGRES_PASSWORD` | Database password (choose a strong one) | | `VITE_SUPABASE_URL` | Your Supabase project URL | | `VITE_SUPABASE_ANON_KEY` | Supabase anon/public key | | `SUPABASE_SERVICE_ROLE_KEY` | Supabase service role key (task-runner) | | `API_KEY_ENCRYPTION_KEY` | Shared 32-byte hex/base64 AES-256 key used by Edge Functions and the task runner | | `WEBHOOK_SECRET` | Shared random secret authenticating database webhooks sent to the task runner | ### Optional Variables | Variable | Default | Description | | ------------------------------ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | `POSTGRES_DB` | crewform | Database name | | `POSTGRES_USER` | crewform | Database user | | `POSTGRES_PORT` | 5432 | PostgreSQL port | | `FRONTEND_PORT` | 3000 | Frontend port | | `VITE_APP_URL` | [http://localhost:3000](http://localhost:3000) | Public app URL | | `OPENAI_API_KEY` | — | Fallback OpenAI key | | `ANTHROPIC_API_KEY` | — | Fallback Anthropic key | | `GOOGLE_GENERATIVE_AI_API_KEY` | — | Fallback Google AI key | | `DISCORD_BOT_TOKEN` | — | Bot token for the managed CrewForm Discord bot (from Discord Developer Portal) | | `DISCORD_PUBLIC_KEY` | — | Ed25519 public key for Discord signature verification (required to register an Interactions Endpoint) | ## Database Migrations Migrations run automatically on startup via the `migrate` container. It: 1. Creates a `_migrations` tracking table 2. Runs all `supabase/migrations/*.sql` files in sorted order 3. Skips already-applied migrations 4. Exits after completion To run migrations manually: ```bash theme={null} docker compose run --rm migrate ``` ## Managing the Stack ```bash theme={null} # View logs docker compose logs -f # View logs for a specific service docker compose logs -f task-runner # Restart a service docker compose restart task-runner # Stop all services docker compose down # Stop and remove volumes (⚠️ deletes database!) docker compose down -v # Rebuild after code changes docker compose build --no-cache docker compose up -d ``` ## Updating ### Using the Update Script (Recommended) ```bash theme={null} # Update to the latest version ./docker/update.sh # Or update to a specific tag/branch ./docker/update.sh v1.2.0 ``` The script will: 1. Pull the latest code 2. Stop running containers (data is preserved) 3. Rebuild images 4. Restart services (migrations run automatically) ### Manual Update ```bash theme={null} # 1. Pull latest code git pull origin main # 2. Check for new environment variables diff .env .env.example # 3. Rebuild and restart docker compose down docker compose build --no-cache docker compose up -d # 4. Verify migrations ran docker compose logs migrate ``` > **💡 Tip:** Always check `.env.example` after updating — new features may require additional environment variables. ## Troubleshooting ### Migrations fail ```bash theme={null} # Check migration logs docker compose logs migrate # Run migrations manually with verbose output docker compose run --rm migrate ``` ### Frontend shows blank page * Ensure `VITE_SUPABASE_URL` and `VITE_SUPABASE_ANON_KEY` are set correctly * Check nginx logs: `docker compose logs frontend` ### Task runner not processing tasks * Check that `SUPABASE_SERVICE_ROLE_KEY` is set * View logs: `docker compose logs -f task-runner` * Ensure the task-runner can reach the Supabase URL ### Database connection issues * Verify `POSTGRES_PASSWORD` matches across services * Check postgres health: `docker compose exec postgres pg_isready` ## Ollama Integration (Local AI) Run AI models **entirely on your own hardware** — no API keys, no external calls, complete data sovereignty. ### 1. Install Ollama ```bash theme={null} # macOS / Linux curl -fsSL https://ollama.com/install.sh | sh # Or via Docker (recommended for servers) docker run -d --name ollama -p 11434:11434 -v ollama:/root/.ollama ollama/ollama ``` ### 2. Pull Models ```bash theme={null} # Pull one or more models ollama pull llama3.3 ollama pull qwen2.5 ollama pull deepseek-r1:8b ollama pull mixtral ollama pull phi4 ollama pull gemma2 # Verify ollama list ``` ### 3. Configure in CrewForm 1. Go to **Settings → LLM Setup** 2. Find **Ollama (Local)** in the provider list 3. Enter any placeholder value as the API key (e.g. `ollama`) — Ollama doesn't need one 4. Save and start creating agents with your local models > **💡** No API key is actually sent to Ollama. The task runner connects to `http://localhost:11434/v1` using the OpenAI-compatible API. ### Docker Networking If both CrewForm and Ollama run in Docker, the task runner can't reach `localhost:11434`. Use one of these approaches: **Option A: Host networking (simplest)** ```yaml theme={null} # In docker-compose.yml, add to the task-runner service: task-runner: extra_hosts: - "host.docker.internal:host-gateway" ``` Then Ollama is reachable at `http://host.docker.internal:11434/v1`. **Option B: Add Ollama to docker-compose** ```yaml theme={null} # Add as a new service in docker-compose.yml: ollama: image: ollama/ollama ports: - "11434:11434" volumes: - ollama_data:/root/.ollama deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] # Remove if no GPU volumes: ollama_data: ``` Then Ollama is reachable at `http://ollama:11434/v1` from the task runner. ### Air-Gapped Setup For fully offline / air-gapped deployments: 1. Pull models on a machine with internet: `ollama pull llama3.3` 2. Copy the model directory (`~/.ollama/models/`) to the target machine 3. Start Ollama on the target: `ollama serve` 4. Deploy CrewForm with Docker Compose — no external API keys needed 5. All AI inference stays on-premises ### Supported Models CrewForm ships with 11 pre-configured Ollama models: | Model | Size | Best For | | ----------------- | ----- | -------------------------- | | Llama 3.3 70B | 40 GB | General reasoning | | Qwen 2.5 32B | 18 GB | Code + multilingual | | DeepSeek R1 8B | 5 GB | Chain-of-thought reasoning | | Mixtral 8x7B | 26 GB | Multi-expert tasks | | Phi-4 14B | 8 GB | Compact but capable | | Gemma 2 9B | 5 GB | Google's efficient model | | Mistral Small 24B | 13 GB | Fast inference | | Command R 35B | 20 GB | RAG + retrieval | | Llama 3.2 3B | 2 GB | Edge / low-resource | | Qwen 2.5 Coder 7B | 4 GB | Code generation | | DeepSeek R1 1.5B | 1 GB | Ultralight tasks | > **RAM Guide:** Plan for \~1.2× the model file size in available RAM. A 5 GB model needs \~6 GB free. ## Production Considerations * **HTTPS**: Put a reverse proxy (Caddy, Traefik, or nginx) in front with TLS * **Backups**: Schedule `pg_dump` via cron * **Monitoring**: Add health check endpoints and uptime monitoring * **Secrets**: Use Docker secrets or a vault for sensitive values * **Memory**: Monitor task-runner memory usage with AI provider calls * **GPU**: For Ollama, add GPU passthrough for significantly faster inference # Troubleshooting Source: https://docs.crewform.tech/troubleshooting # Troubleshooting Common issues and solutions for CrewForm Cloud and self-hosted deployments. ## Agent & Task Execution ### Agent task stays in "Pending" state **Cause**: The task runner isn't running or can't connect to Supabase. **Solution**: 1. Verify the task runner is running: check for `Task runner listening...` in the logs 2. Check `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY` in the task runner's `.env` 3. For self-hosted: ensure the task runner container is healthy (`docker compose ps`) ### "No API key found for provider" error **Cause**: The LLM provider key isn't configured or is incorrectly encrypted. **Solution**: 1. Go to **Settings → API Keys** 2. Delete the existing key for the provider 3. Re-add the key (it will be re-encrypted with AES-256-GCM) ### Agent returns empty or truncated responses **Cause**: Max tokens is set too low, or the model is hitting context limits. **Solution**: 1. Open the agent → increase **Max Tokens** (try 4096) 2. If using a knowledge base with large documents, reduce chunk size 3. Try a model with a larger context window (e.g., `gemini-1.5-pro` at 1M tokens) ### Task fails with "Rate limit exceeded" **Cause**: Too many requests to the LLM provider in a short time. **Solution**: 1. Space out task executions 2. For pipeline teams, increase the delay between steps 3. Consider using a provider with higher rate limits (e.g., OpenRouter) 4. For Ollama local models: no rate limits apply *** ## Knowledge Base / RAG ### Documents not being found in knowledge search **Cause**: Embeddings may not have been generated, or the query doesn't match the content semantically. **Solution**: 1. Check the knowledge base page — documents should show "Indexed" status 2. Try rephrasing the query to match document language more closely 3. Upload more specific, focused documents rather than large general ones 4. Ensure the embedding model has finished processing (check task runner logs) ### "knowledge\_search tool not found" error **Cause**: The agent doesn't have a knowledge base attached. **Solution**: 1. Open the agent → **Knowledge Base** tab 2. Upload at least one document 3. Re-run the task *** ## MCP Server Publishing ### Claude Desktop doesn't show CrewForm tools **Solution**: 1. Verify your MCP config in Claude Desktop Settings → Developer → MCP Servers 2. Check the JSON syntax — common issue is missing commas or quotes 3. Restart Claude Desktop after any config change 4. Verify the MCP API key starts with `cf_mcp_` ### "Unauthorized" error when calling MCP tools **Cause**: Invalid or expired MCP API key. **Solution**: 1. Go to **Settings → MCP Servers** 2. Generate a new MCP API key 3. Update your client config with the new key ### Published agent not appearing in MCP tool list **Solution**: 1. Open the agent — verify the **MCP Published** button is green 2. Check that the agent belongs to the same workspace as your MCP API key 3. Wait 10-15 seconds for the tool list to refresh *** ## Messaging Channels ### Discord bot not responding **Solution**: 1. Verify the bot token in **Settings → Channels → Discord** 2. Check that the bot has been invited to the server with correct permissions (Send Messages, Read Message History) 3. Ensure the correct guild and channel are selected 4. Check task runner logs for connection errors ### Slack messages not triggering agents **Solution**: 1. Re-authenticate the Slack OAuth connection in **Settings → Channels → Slack** 2. Verify the bot is added to the channel where you're sending messages 3. Check that the Slack app has the required scopes ### Telegram bot not responding **Solution**: 1. Verify the bot token from [@BotFather](https://t.me/BotFather) 2. Make sure you've sent `/start` to your bot first 3. For group chats: the bot must be an admin or have group privacy disabled *** ## Self-Hosting (Docker) ### Container health check failing **Solution**: ```bash theme={null} # Check container status docker compose ps # View logs for the failing container docker compose logs app docker compose logs task-runner # Restart all containers docker compose down && docker compose up -d ``` ### Database migration errors **Solution**: 1. Ensure you're running migrations in numeric order 2. Connect to your PostgreSQL instance and check which migrations have been applied 3. For fresh installs, run the migration script: `bash scripts/migrate.sh` ### "CORS error" or "Unable to fetch" in browser **Cause**: Nginx proxy or environment variable misconfiguration. **Solution**: 1. Check `APP_URL` in your `.env` matches the URL you're accessing 2. Verify nginx config routes `/api` and `/mcp` to the correct backend ports 3. For SSL: ensure certificates are valid and nginx is configured for HTTPS ### High memory usage / OOM crashes **Solution**: 1. Add memory limits to `docker-compose.yml`: ```yaml theme={null} services: task-runner: deploy: resources: limits: memory: 2G ``` 2. Reduce concurrent task execution in task runner config 3. Monitor with `docker stats` *** ## Observability & Tracing ### Langfuse traces not appearing **Solution**: 1. Verify `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, and `LANGFUSE_HOST` are set in the task runner's `.env` 2. Check that `ENABLE_TRACING=true` is set 3. Allow 30-60 seconds for traces to appear in the Langfuse dashboard 4. Check task runner logs for Langfuse connection errors ### OpenTelemetry export failing **Solution**: 1. Verify `OTEL_EXPORTER_OTLP_ENDPOINT` is correct 2. Ensure your collector (Jaeger, Grafana Tempo, Datadog) is running and accessible 3. Check firewall rules allow outbound connections to the OTLP endpoint *** ## Common Environment Issues ### "Missing environment variable" on startup **Solution**: 1. Compare your `.env` against `.env.example` — new features may require new variables 2. After pulling updates, always check `.env.example` for new entries 3. Required variables: `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `ENCRYPTION_KEY` ### Different behavior between local and production **Cause**: Environment variable differences. **Solution**: 1. Compare `.env.local` (development) with your production `.env` 2. Ensure `VITE_APP_URL` points to the correct domain in production 3. Check that the task runner's `.env` has the correct production Supabase URL *** ## Still Need Help? * **Discord**: Join our community at [discord.gg/TAFasJCTWs](https://discord.gg/TAFasJCTWs) * **GitHub Issues**: [github.com/CrewForm/crewform/issues](https://github.com/CrewForm/crewform/issues) * **Email**: [team@crewform.tech](mailto:team@crewform.tech) # Tutorial chatbot Source: https://docs.crewform.tech/tutorial-chatbot # Tutorial: Build a Customer Support Chatbot Build a fully functional customer support chatbot in 10 minutes using CrewForm. By the end of this tutorial, your chatbot will answer customer questions using your company's knowledge base and respond via Slack, Discord, or Telegram. ## What You'll Build A customer support agent that: * Answers product questions using your uploaded documentation * Maintains a professional, empathetic tone using a voice profile * Delivers responses via your team's messaging channels * Runs 24/7 without intervention ## Prerequisites * A CrewForm account ([sign up free](https://app.crewform.tech)) * An LLM API key (OpenAI, Anthropic, or Google) * Optionally: a Slack, Discord, or Telegram bot token ## Step 1: Add Your API Key 1. Go to **Settings → API Keys** 2. Click **Add Key** and select your provider (e.g., Anthropic) 3. Paste your API key and click **Save** > Your key is encrypted with AES-256-GCM before storage and never stored in plaintext. ## Step 2: Create the Support Agent 1. Navigate to **Agents → New Agent** 2. Fill in the details: | Field | Value | | --------------- | --------------------------------------------------------------------- | | **Name** | Customer Support Bot | | **Description** | Answers customer questions about our product using the knowledge base | | **Model** | `claude-sonnet-4-20250514` (or your preferred model) | | **Temperature** | 0.3 (lower = more consistent, factual answers) | 3. Write a system prompt: ``` You are a helpful customer support representative for our company. Rules: - Always be polite, empathetic, and professional - Answer questions ONLY based on the knowledge base provided - If you don't know the answer, say: "I don't have that information yet — let me connect you with our team at support@yourcompany.com" - Keep responses concise (under 200 words) - Use bullet points for multi-step instructions - Never make up product features or pricing ``` 4. Click **Create Agent** ## Step 3: Add a Knowledge Base 1. Open your agent → click the **Knowledge Base** tab 2. Click **Upload Documents** 3. Upload your product documentation, FAQ files, or help center content (text, markdown, or PDF) 4. CrewForm will automatically chunk your documents and create vector embeddings > **Tip**: Upload your most-asked FAQ document first. You can always add more documents later. ## Step 4: Configure a Voice Profile 1. Click the **Voice Profile** tab on your agent 2. Select **Empathetic** as the tone preset 3. Add custom instructions: ``` Always refer to users as "you" (not "the user"). End every response with "Is there anything else I can help with?" Use simple, jargon-free language. ``` 4. Click **Save Voice Profile** ## Step 5: Test Your Agent 1. Go to **Tasks → New Task** 2. Select your Customer Support Bot 3. Enter a test question: *"How do I reset my password?"* 4. Click **Run Task** 5. Review the response — it should draw from your uploaded knowledge base ## Step 6: Connect a Messaging Channel (Optional) ### Slack 1. Go to **Settings → Channels → Slack** 2. Follow the OAuth flow to connect your Slack workspace 3. Configure which channel the bot listens in ### Discord 1. Go to **Settings → Channels → Discord** 2. Enter your Discord bot token 3. Select the guild and channels ### Telegram 1. Go to **Settings → Channels → Telegram** 2. Enter your bot token from [@BotFather](https://t.me/BotFather) Once connected, customers can message your bot directly in the channel, and the agent responds automatically. ## Step 7: Set Up Output Routes To also deliver responses to specific destinations: 1. Go to **Settings → Output Routes** 2. Add a webhook, Slack channel, or other destination 3. Open your agent → scroll to **Output Routes** → select the specific channels ## What's Next? * **Scale up**: Create a [Pipeline Team](./pipeline-teams.md) with a triage agent that routes questions to specialized agents (billing, technical, general) * **Add context**: Upload more documents to your knowledge base to improve answer coverage * **Monitor**: Check the **Analytics** page for token usage, response times, and cost tracking * **Publish as MCP tool**: [Publish your agent](./mcp-server-publishing.md) so Claude Desktop or Cursor can call it directly # Tutorial content pipeline Source: https://docs.crewform.tech/tutorial-content-pipeline # Tutorial: Build a Content Pipeline Team Create a multi-agent content pipeline that researches a topic, writes an article, and edits it — all automatically. This tutorial showcases CrewForm's Pipeline Team mode, where agents execute sequentially, each building on the previous agent's output. ## What You'll Build A 3-agent pipeline that: 1. **Researcher** — Gathers information and key points on a topic 2. **Writer** — Transforms research into a polished article draft 3. **Editor** — Reviews, refines, and produces the final version ## Prerequisites * A CrewForm account with at least one LLM API key configured * 5–10 minutes ## Step 1: Create the Research Agent 1. Go to **Agents → New Agent** 2. Configure: | Field | Value | | --------------- | -------------------------------------- | | **Name** | Topic Researcher | | **Model** | `gpt-4o` or `claude-sonnet-4-20250514` | | **Temperature** | 0.5 | 3. System prompt: ``` You are a thorough research analyst. Given a topic, you produce a comprehensive research brief. Your output must include: - **Key Facts**: 5-8 important facts or statistics - **Main Arguments**: 3-4 key perspectives or angles - **Target Audience**: Who would read an article on this topic - **Suggested Structure**: An outline for a 1,000-word article - **Sources to Reference**: Suggest specific types of sources that would strengthen the article Format your output as clean markdown with clear headers. ``` 4. Click **Create Agent** ## Step 2: Create the Writer Agent 1. Create another agent: | Field | Value | | --------------- | ------------------------------------ | | **Name** | Content Writer | | **Model** | `claude-sonnet-4-20250514` | | **Temperature** | 0.7 (slightly higher for creativity) | 2. System prompt: ``` You are a professional content writer. You receive a research brief and transform it into a polished, engaging article. Rules: - Write approximately 800-1,200 words - Use an engaging, conversational tone suitable for a tech blog - Include a compelling introduction and conclusion - Use headers (H2/H3) to organize sections - Incorporate the key facts and arguments from the research brief - Write for the target audience identified in the brief - Do NOT add content that wasn't in the research brief — stay factual Output: A complete article in markdown format. ``` ## Step 3: Create the Editor Agent 1. Create a third agent: | Field | Value | | --------------- | -------------------------- | | **Name** | Content Editor | | **Model** | `claude-sonnet-4-20250514` | | **Temperature** | 0.2 (low for precision) | 2. System prompt: ``` You are a meticulous senior editor. You receive a draft article and produce the final, publish-ready version. Your editing checklist: 1. Fix any grammar, spelling, or punctuation errors 2. Improve sentence clarity and flow 3. Ensure consistent tone and voice 4. Check that the article has a strong opening hook 5. Verify logical flow between sections 6. Add a compelling meta description (under 160 characters) 7. Suggest 3-5 SEO-friendly tags Output format: ## Final Article [The edited article in markdown] ## Meta Description [Under 160 characters] ## Tags [Comma-separated list] ## Editor's Notes [Any significant changes or suggestions for the author] ``` ## Step 4: Create the Pipeline Team 1. Go to **Teams → New Team** 2. Select **Pipeline** mode 3. Name it: *Content Production Pipeline* 4. Add agents in order: * **Step 1**: Topic Researcher * **Step 2**: Content Writer * **Step 3**: Content Editor 5. Click **Create Team** > **How pipelines work**: Each agent receives the previous agent's output as its input. The Researcher's output becomes the Writer's input, and the Writer's output becomes the Editor's input. ## Step 5: Run the Pipeline 1. Go to **Teams → Content Production Pipeline** 2. Click **Run Team** 3. Enter a topic: *"The impact of Agent-to-Agent protocols on enterprise AI adoption"* 4. Watch the pipeline execute: * The Researcher produces a research brief * The Writer transforms it into an article * The Editor polishes and publishes the final version 5. View the final result in the team run detail page ## Step 6: Visualize in the Workflow Builder 1. Open your team → click **Visual Builder** 2. See your 3 agents arranged as connected nodes in the canvas 3. Each node shows the agent name, model, and execution status 4. Use this view to rearrange, add/remove agents, or branch the pipeline ## Step 7: Deliver Results Automatically Set up an output route so finished articles are delivered automatically: 1. Go to **Settings → Output Routes → Add Route** 2. Choose **Webhook** and enter your CMS API endpoint, or 3. Choose **Slack** to post finished articles to a `#content-review` channel 4. On the Editor agent, set **Output Routes** to your chosen destination Now every time you run the pipeline, the final article lands where your team needs it. ## Extend the Pipeline Here are ideas to make this pipeline more powerful: * **Add a 4th agent**: An SEO Optimizer that adds internal links, adjusts headings, and optimizes keyword density * **Fan-out**: Use [Fan-Out Pipelines](./pipeline-teams.md) to have multiple writers produce competing drafts, then a merge agent picks the best one * **Schedule**: Use **Zapier Integration** to trigger the pipeline on a schedule (daily content generation) * **Knowledge Base**: Give the Researcher agent a knowledge base with your company's style guide and brand guidelines ## What's Next? * [Orchestration Teams](./orchestration-teams.md) — Let a brain agent decide which workers to delegate to dynamically * [Collaboration Teams](./collaboration-teams.md) — Agents discuss and reach consensus on complex decisions * [Visual Workflow Builder](./visual-workflow-builder.md) — Drag-and-drop canvas for designing workflows # Tutorial mcp publishing Source: https://docs.crewform.tech/tutorial-mcp-publishing # Tutorial: Publish Agents as MCP Tools Expose your CrewForm agents as MCP (Model Context Protocol) tools that Claude Desktop, Cursor, and any MCP-compatible AI client can call directly. This turns your agents into universal AI building blocks. ## What You'll Build By the end of this tutorial, you'll have: * A CrewForm agent published as an MCP tool * Claude Desktop configured to call your agent * A working end-to-end demo where Claude uses your agent as a tool ## What is MCP? The [Model Context Protocol](https://modelcontextprotocol.io) is an open standard for connecting AI systems with external tools and data sources. When you publish a CrewForm agent as an MCP server, any MCP-compatible client can discover and invoke it — just like calling a function. > **CrewForm is one of the few platforms that supports MCP as both client AND server.** Your agents can consume external MCP tools *and* be consumed by other AI systems. ## Prerequisites * A CrewForm account with at least one configured agent * [Claude Desktop](https://claude.ai/download) installed (or Cursor) * An internet-accessible CrewForm instance (cloud or self-hosted with public URL) ## Step 1: Create an Agent Worth Publishing Let's create a useful agent that Claude Desktop will call as a tool. Example: a code review agent. 1. Go to **Agents → New Agent** 2. Configure: | Field | Value | | --------------- | ---------------------------------------------------------------------------------------- | | **Name** | Code Reviewer | | **Description** | Reviews code for bugs, security issues, and best practices. Returns a structured report. | | **Model** | `claude-sonnet-4-20250514` | | **Temperature** | 0.2 | 3. System prompt: ``` You are a senior code reviewer specializing in TypeScript, Python, and React. When given code to review, analyze it for: 1. **Bugs**: Logic errors, off-by-one errors, null reference issues 2. **Security**: SQL injection, XSS, insecure data handling 3. **Performance**: N+1 queries, unnecessary re-renders, memory leaks 4. **Best Practices**: Naming conventions, code organization, DRY violations Output format: ## Code Review Summary **Overall Rating**: ⭐⭐⭐⭐ (X/5) ### Issues Found | # | Severity | Category | Description | Line(s) | |---|----------|----------|-------------|---------| ### Recommendations [Numbered list of improvements] ### Positive Notes [What the code does well] ``` 4. Click **Create Agent** ## Step 2: Publish as MCP Tool 1. Open your **Code Reviewer** agent 2. Click the **MCP Publish** button in the header bar 3. The button changes to **MCP Published** (green ✅) That's it. Your agent is now discoverable and callable via MCP. > **What happens behind the scenes**: The agent becomes available at your workspace's MCP endpoint as a tool named `code_reviewer` (auto-derived from the agent name). The tool accepts a `message` string parameter and executes the full agent — same model, system prompt, tools, knowledge base, and voice profile as running from the UI. ## Step 3: Generate an MCP API Key 1. Go to **Settings → MCP Servers** 2. Click **Generate MCP API Key** 3. A key prefixed with `cf_mcp_` will be generated 4. Copy the key — you'll need it for the next step > Each key is scoped to a single workspace. Only that workspace's published agents are visible to clients using that key. ## Step 4: Configure Claude Desktop 1. Open Claude Desktop → **Settings → Developer → MCP Servers** 2. Add a new server with this configuration: ```json theme={null} { "mcpServers": { "crewform": { "url": "https://runner.crewform.tech/mcp", "headers": { "Authorization": "Bearer cf_mcp_your_key_here" } } } } ``` 3. Restart Claude Desktop > **Self-hosted?** Replace the URL with your task runner's public URL: `https://your-domain.com/mcp` ## Step 5: Test It 1. Open a new conversation in Claude Desktop 2. Ask Claude something like: ``` Can you review this TypeScript function for issues? function getUser(id: string) { const user = db.query("SELECT * FROM users WHERE id = " + id); return user[0]; } ``` 3. Claude will recognize that it has a `code_reviewer` tool available and call your CrewForm agent 4. Your agent executes with its full configuration and returns the review 5. Claude presents the result in the conversation ## Step 6: Configure Cursor (Alternative) If you prefer Cursor over Claude Desktop: 1. Create `.cursor/mcp.json` in your project root: ```json theme={null} { "mcpServers": { "crewform": { "url": "https://runner.crewform.tech/mcp", "headers": { "Authorization": "Bearer cf_mcp_your_key_here" } } } } ``` 2. Restart Cursor — your CrewForm agents now appear as available tools ## Publishing Multiple Agents You can publish as many agents as you want from the same workspace: 1. Open each agent → click **MCP Publish** 2. All published agents appear as separate tools under the same MCP server 3. Tool names are auto-derived: "Data Analyst" → `data_analyst`, "Bug Fixer" → `bug_fixer` Claude Desktop (or any MCP client) will see all published agents as available tools and choose the right one based on context. ## Unpublishing To remove an agent from MCP: 1. Open the agent → click **MCP Published** (the green button) 2. It toggles back to unpublished immediately 3. The agent disappears from the MCP tool list ## Advanced: Full Team Execution When you publish an agent that belongs to a team, the MCP tool still executes just that individual agent. If you want to trigger a full pipeline or orchestrator team via MCP, create a dedicated "gateway" agent whose system prompt delegates to the appropriate team. ## Troubleshooting | Issue | Solution | | ---------------------------- | ------------------------------------------------------------------- | | Claude doesn't show the tool | Restart Claude Desktop after adding the config | | "Unauthorized" error | Check your `cf_mcp_` key is correct and not expired | | Tool call times out | Complex agents may take longer — consider increasing client timeout | | Agent not in tool list | Make sure the agent is published (green MCP Published button) | ## What's Next? * [A2A Protocol](./a2a-protocol.md) — Let external agents discover and delegate tasks to your CrewForm agents * [AG-UI Protocol](./ag-ui-protocol.md) — Build rich, interactive agent UIs with streaming * [Knowledge Base](./knowledge-base.md) — Give your published agents access to your documents # Visual Workflow Builder Source: https://docs.crewform.tech/visual-workflow-builder Interactive canvas for building, visualizing, and monitoring multi-agent workflows in real-time. # Visual Workflow Builder CrewForm's Visual Workflow Builder transforms the team configuration experience from static forms into an interactive, real-time orchestration dashboard. Built on React Flow, it provides drag-and-drop agent placement, live execution visualization, and deep observability tools. ## Overview The Visual Workflow Builder is available on any Team page via the **Canvas** tab. It supports all three team modes: | Mode | Layout | Description | | ----------------- | --------------------- | -------------------------------- | | **Pipeline** | Top-to-Bottom | Sequential chain of agent steps | | **Orchestrator** | Top-to-Bottom (wider) | Brain agent delegates to workers | | **Collaboration** | Left-to-Right | Agents discuss in parallel | ## Getting Started 1. Navigate to any Team and switch to the **Canvas** tab 2. **Drag agents** from the sidebar palette onto the canvas 3. **Connect nodes** by dragging from a node's bottom handle to another node's top handle 4. The configuration **auto-saves** when you add, remove, or reorder nodes 5. Use **Auto-layout** (press `L`) to arrange nodes automatically ## Canvas Features ### Node Types * **Start Node** - Entry point of the workflow (green, with breathing pulse animation) * **Agent Nodes** - Represent individual agents with role badges (Brain/Worker/Reviewer) * **Fan-Out Node** - Splits into parallel branches (labeled "fan-out" on the first edge) * **Branch Agent Nodes** - Parallel agents that execute concurrently within a fan-out step * **Merge Node** - Converges branch outputs back into a single result * **End Node** - Terminal node of the workflow (red) All nodes use **glassmorphism styling** with frosted glass backgrounds, backdrop blur, translucent borders, and hover lift effects. ### Fan-Out Visualization When a pipeline includes [fan-out steps](/pipeline-teams#fan-out-parallel-branching), the canvas renders a branching pattern: ``` ... → Previous Step → [Fan-Out] → Branch Agent A ─┐ → Branch Agent B ─┤→ [Merge Agent] → Next Step → ... → Branch Agent C ─┘ ``` * The **fan-out node** splits into multiple parallel edges, each leading to a branch agent * **Branch agents** appear as standard agent nodes, arranged side-by-side * A **merge node** collects all branch outputs — this is the agent that synthesizes results * During execution, each branch shows its **individual status** (Idle → Running → Completed/Failed) * The merge node only starts executing once all branches (or surviving branches, depending on failure mode) complete ### Drag and Drop Drag agents from the sidebar palette onto the canvas. The sidebar shows all agents in your workspace with: * **Search and filter** - Appears automatically when you have more than five agents. Filter by name or model. * **Agent count badge** - Shows filtered and total count * **Drag handle** - Grab and drop agents directly onto the canvas ### Node Interaction * **Click** a node to open the **Detail Popup**, which shows agent configuration, model, role, and execution status * **Right-click** a node or the canvas background for a **Context Menu** with quick actions: * Delete node * Auto-layout * Set as Brain (orchestrator mode) * Fit View * Go to Agent ### Undo and Redo Full undo/redo support with a 30-entry history stack. Any node addition, deletion, or repositioning can be undone. *** ## Live Execution Visualization When a team run is active, the canvas transforms into a live monitoring dashboard: ### Execution States Each agent node shows its current state in real-time: | State | Visual | Description | | ------------- | ------------------------------------------ | --------------------- | | **Idle** | Default styling | Waiting to execute | | **Running** | Blue pulsing border glow and spinner badge | Currently processing | | **Completed** | Green border and checkmark badge | Finished successfully | | **Failed** | Red border and error badge | Encountered an error | ### Camera Auto-Follow When a run is active, the canvas **automatically pans** to the currently executing agent node with smooth, debounced transitions. Toggle this behavior with the camera button in the toolbar. ### Execution Timeline A horizontal progress rail appears below the canvas during runs, showing: * Step-by-step progress with status indicators * Click any step to **pan the camera** to that agent node * Real-time updates as agents start and complete ### Animated Edges During execution, edges animate with a flowing dashed pattern to indicate the direction of data flow between agents. *** ## Observability Panels ### Transcript Panel Toggle with the transcript button in the toolbar or press `T`. A real-time message feed showing inter-agent communication during execution: * **Color-coded** by agent (each agent gets a unique color) * **Filter buttons** - All, Delegations, Results, System * **Tool call expansion** - Shows which tools were called, success or failure, and duration * **Token count** per message * **Auto-scroll** to the latest message * **Live badge** - Shows a green pulse indicator during active runs ### Tool Activity Heatmap Toggle with the activity button in the toolbar. Aggregated tool and MCP usage statistics across the entire run: * **Call count** per tool * **Success rate** - Color-coded bar (green for high, amber for medium, red for low success rates) * **Average duration** in milliseconds * **Overall success rate** summary bar at the top * Sorted by most-used tools *** ## Keyboard Shortcuts Press `?` or click the keyboard button to view all shortcuts. ### Navigation | Shortcut | Action | | -------- | ------------------------------------- | | `F` | Fit view (zoom to fit all nodes) | | `L` | Auto-layout (dagre-based arrangement) | | Scroll | Zoom in and out | | Drag | Pan canvas | ### Editing | Shortcut | Action | | ------------------------------- | -------------------- | | `Cmd+Z` or `Ctrl+Z` | Undo | | `Cmd+Shift+Z` or `Ctrl+Shift+Z` | Redo | | `Cmd+A` or `Ctrl+A` | Select all nodes | | `Delete` | Remove selected node | ### Panels | Shortcut | Action | | -------- | --------------------------------- | | `T` | Toggle transcript panel | | `?` | Toggle keyboard shortcuts overlay | | `Escape` | Close all panels or deselect | *** ## Toolbar The info panel toolbar at the top-left shows: * **Mode label** - Pipeline, Orchestrator, or Collaboration * **Agent count** - Number of agent nodes on the canvas * **Saving indicator** - Animated text during auto-save * **Undo and Redo** buttons with enabled and disabled states * **Auto-layout** button * **Camera follow** toggle (during active runs) * **Transcript** toggle (during active runs) * **Tool activity** toggle (during active runs) * **Keyboard shortcuts** button *** ## Configuration The canvas reads and writes to the team's configuration object. When you add, remove, or reorder nodes, the configuration is validated and saved: * **Pipeline** - Updates `agent_order` array * **Orchestrator** - Updates `brain_agent_id` and `worker_agent_ids` * **Collaboration** - Updates `participant_agent_ids` Invalid configurations (such as disconnected nodes or a missing brain) show an error toast that auto-dismisses. ## Design System All canvas overlays, including popups, context menus, and panels, follow a consistent **glassmorphism** design language: * Backdrop blur for frosted glass effect * Semi-transparent backgrounds * Subtle borders * Smooth entry animations with scale and opacity transitions * Consistent with CrewForm's dark theme aesthetic # Workflow Templates Source: https://docs.crewform.tech/workflow-templates Create, browse, and install reusable AI workflow blueprints with fill-in-the-blank variables. # Workflow Templates Workflow Templates are reusable blueprints that bundle agents, teams, and triggers into a single installable package. Users fill in a few variables and get a fully wired workflow in one click. ## Overview A template captures your entire workflow setup — agents with their prompts, team configuration, pipeline steps, and scheduled triggers — and parameterizes it with `{{variable}}` placeholders. When someone installs your template, they fill in those variables and CrewForm automatically creates everything for them. ``` Template Definition ├── Agents (1 or more) → Created with resolved prompts ├── Team (optional) → Pipeline/Orchestrator/Collaboration │ └── Steps → Auto-wired to created agents └── Trigger (optional) → CRON schedule or Webhook ``` ## Browsing Templates Navigate to **Marketplace → Templates** to browse published workflow templates. Each template card shows: * **Icon & Name** — Quick visual identification * **Category** — Coaching, Research, Content, DevOps, Reporting, etc. * **Description** — What the template does * **Install Count** — Community popularity * **Resource Summary** — Number of agents, team mode, and trigger type Click any card to open the Install Modal. ## Installing a Template 1. Click a template card in the Marketplace 2. Review **what will be created** — agents, team, and trigger details 3. **Fill in the variables** — each template defines its own set of configurable values 4. Click **Install Template** 5. CrewForm automatically creates all resources in your workspace ### Variable Resolution Variables use `{{mustache}}` syntax. During installation, every `{{variable}}` in the template definition (agent prompts, task descriptions, team names, etc.) is replaced with the value you provide. **Example:** A template with `{{sport}}` and `{{age_group}}` variables in the agent's system prompt: ``` You are a {{sport}} coach for {{age_group}} players. Focus on: {{focus_areas}} ``` When installed with `sport = "rugby"`, `age_group = "under 9s"`, and `focus_areas = "tackling, passing, positioning"`: ``` You are a rugby coach for under 9s players. Focus on: tackling, passing, positioning ``` ## Creating a Template There are two ways to create a workflow template: ### From the Marketplace 1. Click **+ Create Template** in the Marketplace header 2. Follow the 4-step wizard: | Step | What You Do | | ---------------- | -------------------------------------------------------------------------------------- | | **1. Select** | Pick agents and optionally a team from your workspace | | **2. Variables** | Auto-scans `{{variable}}` patterns from prompts; define labels, placeholders, defaults | | **3. Metadata** | Set name, description, icon, category, tags, and optional CRON/webhook trigger | | **4. Preview** | Review everything before publishing | ### From an Agent 1. Open any agent's detail page 2. Click the **Template** button in the header 3. The wizard opens with that agent pre-selected ### Variable Tips * Use descriptive variable names: `{{target_audience}}` not `{{var1}}` * Provide sensible defaults so users can install quickly * Mark variables as required only if the template won't work without them * Variables work anywhere in the template definition — prompts, names, descriptions, trigger configs ## Built-in Templates CrewForm ships with 5 starter templates: ### 🏉 Weekly Sports Coach A single-agent workflow with a CRON trigger that delivers weekly coaching tips. **Variables:** `sport`, `age_group`, `focus_areas`, `cron_expression` **Creates:** 1 agent + 1 CRON trigger (default: every Friday at 9am) *** ### 📝 Content Research Pipeline A 3-agent pipeline for topic research, content writing, and editing. **Variables:** `topic`, `target_audience`, `tone` **Creates:** 3 agents (Researcher, Writer, Editor) + 1 pipeline team *** ### 📰 Daily News Digest A 2-agent pipeline that gathers and summarizes industry news on a schedule. **Variables:** `industry`, `news_sources`, `output_format` **Creates:** 2 agents (Gatherer, Summarizer) + 1 pipeline team + 1 CRON trigger (weekdays at 7am) *** ### 🔍 Code Review Assistant A single-agent webhook-triggered workflow for automated code reviews. **Variables:** `language`, `coding_standards`, `severity_level` **Creates:** 1 agent + 1 webhook trigger *** ### 📊 Weekly Report Generator A 2-agent pipeline for data analysis and report writing on a weekly schedule. **Variables:** `department`, `key_metrics`, `stakeholders` **Creates:** 2 agents (Analyst, Writer) + 1 pipeline team + 1 CRON trigger (Mondays at 8am) ## Template Definition Schema For advanced users, templates are stored as JSONB with this structure: ```typescript theme={null} interface TemplateDefinition { agents: TemplateAgentDef[] // Required: at least 1 agent team: TemplateTeamDef | null // Optional: team configuration trigger: TemplateTriggerDef | null // Optional: CRON or webhook } interface TemplateVariable { key: string // Variable key (e.g. "sport") label: string // Display label (e.g. "Sport") type: 'text' | 'number' | 'select' placeholder: string // Input placeholder required: boolean // Must be filled before install default: string // Pre-filled default value } ``` ## Database Templates are stored in the `workflow_templates` table with: * **RLS policies** — creators can manage their own; all users can read published templates * **JSONB storage** — template definitions and variables stored as flexible JSON * **Install counter** — tracks how many times each template has been installed * **Indexes** — optimized for category, tag, and full-text search queries ## Next Steps * [Agents Guide](/agents) — Learn how agents work before templating them * [Pipeline Teams](/pipeline-teams) — Understand team modes for multi-agent templates * [Marketplace](/agents#marketplace) — Browse and install community templates # Zapier testing guide Source: https://docs.crewform.tech/zapier-testing-guide # CrewForm — Zapier Integration Testing Guide > **App URL:** [https://crewform.tech](https://crewform.tech) ## Test Account Credentials | Field | Value | | -------- | -------------------------------- | | Email | `integration-testing@zapier.com` | | Password | `Z@ppt35t@2026` | *** ## Step 1: Log In 1. Go to **[https://crewform.tech/auth](https://crewform.tech/auth)** 2. Enter the email and password above 3. Click **Sign In** 4. You'll land on the **Dashboard** *** ## Step 2: Create Your First Agent An "Agent" is a configured AI assistant — you'll need at least one to test tasks and team runs. 1. Click **Agents** in the left sidebar 2. Click **+ New Agent** 3. Fill in: * **Name:** `Test Agent` * **Model:** Select any model (e.g. `gpt-4o`) * **System Prompt:** `You are a helpful assistant for testing.` 4. Click **Create Agent** *** ## Step 3: Create a Task Tasks are units of work assigned to agents. 1. Click **Tasks** in the left sidebar 2. Click **+ New Task** 3. Fill in: * **Title:** `Test Task` * **Description:** `This is a test task for the Zapier integration.` * **Priority:** `Medium` * **Assign Agent:** Select the `Test Agent` you just created 4. Click **Create Task** *** ## Step 4: Create a Team (Optional) Teams are multi-agent workflows. If you want to test team-related Zapier triggers: 1. Click **Teams** in the left sidebar 2. Click **+ New Team** 3. Fill in: * **Name:** `Test Pipeline` * **Mode:** `Pipeline` 4. Add the `Test Agent` as a step in the pipeline 5. Click **Create Team** *** ## Step 5: Generate an API Key This is the key you'll use to connect CrewForm to Zapier. 1. Click **Settings** in the left sidebar (gear icon at the bottom) 2. Click the **API Keys** tab 3. Click **Generate Key** 4. **Copy the key immediately** — it's only shown once 5. The key will start with `cf_...` > ⚠️ **Important:** Save this key securely. You'll paste it into Zapier when connecting the CrewForm app. *** ## Step 6: Connect to Zapier 1. In Zapier, search for **CrewForm** in the app directory 2. Click **Connect** 3. When prompted, paste the API key you copied in Step 5 4. Zapier will call the `/api-me` endpoint to verify the key — you should see your account name (**Zapier Test**) displayed *** ## Step 7: Test Zapier Triggers & Actions ### Available Triggers | Trigger | What to do in CrewForm to fire it | | ---------------------- | ------------------------------------------------------------ | | **Task Completed** | Go to Tasks → click a task → change status to "Completed" | | **New Task Created** | Create a new task (Step 3 above) | | **Team Run Completed** | Go to Teams → click team → click "Run" → wait for completion | ### Available Actions | Action | What it does | | ------------------ | ----------------------------------- | | **Create Task** | Creates a new task in CrewForm | | **Create Agent** | Creates a new agent in CrewForm | | **Start Team Run** | Kicks off a team run | | **Find Task** | Searches for a task by ID or status | ### Quick Test Workflow Set up a simple Zap to verify the connection: 1. **Trigger:** CrewForm → New Task Created 2. **Action:** Send an email (Gmail, Outlook, etc.) 3. Go back to CrewForm and create a new task 4. Check that Zapier fires and the email is sent *** ## Navigation Reference | Page | URL | What it shows | | ----------- | -------------- | ----------------------------------- | | Dashboard | `/` | Overview stats and recent activity | | Agents | `/agents` | List of AI agents | | Teams | `/teams` | Multi-agent workflows | | Tasks | `/tasks` | Task list with status filters | | Marketplace | `/marketplace` | Browse and install shared agents | | Analytics | `/analytics` | Token usage and cost tracking | | Settings | `/settings` | API Keys, billing, workspace config | *** ## Need Help? * **Docs:** [https://docs.crewform.tech](https://docs.crewform.tech) * **API Reference:** [https://docs.crewform.tech/api-reference](https://docs.crewform.tech/api-reference) * **Email:** [team@crewform.tech](mailto:team@crewform.tech) * **Discord:** [https://discord.gg/TAFasJCTWs](https://discord.gg/TAFasJCTWs)