Tools in Prosponsive are n8n workflows. When you build a workflow that follows the conventions in this guide, Prosponsive automatically discovers it and makes it available to your agents. This guide covers how to structure your workflows, how to design their output for the best display in Prosponsive, and how to connect incoming data to outgoing tool calls.
Third-party software. n8n is a source-available workflow engine developed by n8n GmbH and licensed under the Sustainable Use License. It is an independent product and is not affiliated with Prosponsive. It is the user's responsibility to review and comply with n8n's licensing terms.
Prosponsive periodically scans your n8n instance for workflows it can use as tools. A workflow must meet three requirements to be discovered:
| Requirement | Details |
|---|---|
| Published | The workflow must be toggled to Active (published) in n8n. |
| Webhook trigger | The workflow must start with a Webhook node set to POST with a path value. |
| Not the adapter | The workflow must not be named Prosponsive: n8n Workflow Adapter (that workflow is used internally). |
After discovery, the tool appears in agent tool lists within Prosponsive. Discovery runs on startup and every 15 minutes thereafter.
The tool name is derived automatically from the workflow's display name: converted to lowercase, non-alphanumeric characters removed, spaces replaced with underscores.
| Workflow name | Tool name |
|---|---|
Email Move To Folder | email_move_to_folder |
Search Jira Issues | search_jira_issues |
Get Channel Activity | get_channel_activity |
Changing a workflow's name changes its tool name, which may break agent configurations that reference it.
The description tells the AI agent when and why to use your tool. Prosponsive looks for a description in this order:
Description field in the workflow's Settings (gear icon in n8n). This takes highest priority.Write descriptions from the AI's perspective: "Use this tool when you need to move an email to a different IMAP folder."
Prosponsive discovers your tool's input parameters by scanning Code nodes for common patterns. Use these patterns in your JavaScript code so that Prosponsive can detect parameter names, types, and defaults automatically:
// These patterns are detected by Prosponsive
const name = parameters.name ?? 'World';
const maxResults = body.maxResults || 10;
const includeArchived = parameters.includeArchived ?? false;
From these patterns, Prosponsive infers:
| Parameter | Type | Default |
|---|---|---|
name | string | "World" |
maxResults | number | 10 |
includeArchived | boolean | false |
Parameter names are automatically converted to human-readable descriptions (maxResults becomes "The max results").
How you structure your workflow's output directly affects how results look in Prosponsive conversations. The AI summarizes tool results for the user, and Prosponsive applies formatting rules to the AI's response.
Prosponsive automatically detects short key-value pairs in AI responses and renders them as a compact two-column grid with bold keys. This produces a polished, scannable layout instead of a plain text list.
When your tool returns flat, descriptive fields:
return [{
json: {
"Subject": "Re: Q3 Planning",
"From": "alice@example.com",
"Date": "April 3, 2026",
"Status": "Unread",
"Folder": "INBOX",
"Priority": "Normal"
}
}];
The AI will naturally respond with lines like:
Subject: Re: Q3 Planning
From: alice@example.com
Date: April 3, 2026
Status: Unread
Folder: INBOX
Priority: Normal
Prosponsive renders this as a compact grid:
| Subject: | Re: Q3 Planning | From: | alice@example.com | |
| Date: | April 3, 2026 | Status: | Unread | |
| Folder: | INBOX | Priority: | Normal |
Rules for key-value detection:
Key: Value, Key = Value, or Key - ValueBody:) ends the key-value section — everything after is treated as body content"From" not "sender_email_address"). The AI will echo them as-is, and short keys produce the best two-column layout. If you have more than 8–10 fields, consider omitting less important ones — the compact display works best with focused, scannable data.
json property of output itemsYou can attach an "open in external app" link to any message that a workflow sends to Prosponsive. When present, Prosponsive renders a small external-link icon in the top-right corner of the message bubble. Clicking it opens the URL in the user's default application.
To add a link, include an openLink object in the context data your workflow sends:
| Field | Type | Required | Description |
|---|---|---|---|
openLink.url | string | Yes | The URL to open. Can be any protocol the OS handles: message://, ms-outlook://, https://, slack://, etc. |
openLink.label | string | Yes | Tooltip text shown on hover (e.g., "Open in Mail", "Find in Outlook", "View in browser"). |
Both fields are required. If either is missing or not a string, the link is silently omitted.
Example uses:
message:// on macOS, ms-outlook:// on Windows)https://)slack://)When a workflow sends data to Prosponsive (for example, an email polling workflow posting a new email notification), that data is attached to the message as Request Context — a JSON object you can inspect by clicking the Request Context expander on any message that carries it.
Request Context fields are what make tool parameter mapping possible. In the agent editor, you can configure a tool parameter to read its value directly from a Request Context field rather than asking the user. This is how you build fully automated chains: a trigger workflow brings data in, and the agent uses that data to call tools without any user input.
For example, an email notification workflow might send Request Context containing:
{
"uid": "12345",
"mailbox": "INBOX",
"from": "alice@example.com",
"subject": "Re: Q3 Planning"
}
In the agent editor, you can then map the email_move_to_folder tool's parameters:
uid value from the Request Context. If missing, ask the user.mailbox value from the Request Context. If missing, ask the user.This tells the agent: "When you need to move an email, get the uid and mailbox from the message data automatically, but ask the user which folder to move it to."
Prosponsive samples every message that carries Request Context and discovers all available field paths (including nested fields up to 4 levels deep). The set of available fields is cumulative across the conversation — different workflows or different executions of the same workflow can contribute different fields, and all of them become available for parameter mapping.
Discovered fields populate the Request Context field picker in the Tool Parameter Guidance Builder in the agent editor.
Prosponsive runs a local HTTPS API server (port 3100) that your workflows can call. These are the endpoints used by workflows like imap-new-email to route messages into conversations and invoke AI agents.
Resolves a conversation by name, creating it if it doesn't exist. This is how workflows route messages to a specific conversation in the Prosponsive UI. For example, the imap-new-email workflow uses this to ensure all inbound emails land in the "Email Inbox" conversation.
Request body:
{
"slug": "Email Inbox"
}
| Field | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | The conversation name (e.g., "Email Inbox", "Support Tickets"). Prosponsive derives a URL-safe slug from this value and uses the original value as the display name. |
Response body:
{
"success": true,
"conversationId": "a1b2c3d4-...",
"slug": "Email Inbox"
}
Behavior:
conversationId is returned. Calling this endpoint repeatedly with the same name is safe.Sends a prompt to the active AI provider using a specific agent's system prompt and tool definitions. Does not include conversation history — each call is stateless. This is the primary endpoint for workflows that push data into Prosponsive conversations.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The message text (e.g., "New email from alice@example.com...") |
conversationId | string | Yes | Conversation to add the message to (from /api/conversations/resolve) |
agentId | string | Yes | The agent whose definition to use |
context | object | No | Becomes the message's Request Context. Include openLink here for external app links. |
execution | object | Yes | Execution metadata with executionId, workflowId, and optional startedAt |
Typical usage pattern:
// Step 1: Resolve conversation by name
POST /api/conversations/resolve
{ "slug": "Email Inbox" }
// Returns: { "conversationId": "a1b2c3d4-..." }
// Step 2: Send AI inference into that conversation
POST /api/ai/agent-inference
{
"prompt": "New email from alice@example.com: Re: Q3 Planning",
"conversationId": "a1b2c3d4-...",
"agentId": "executive-assistant-email-agent",
"context": {
"uid": "12345",
"mailbox": "INBOX",
"from": "alice@example.com",
"subject": "Re: Q3 Planning",
"openLink": {
"url": "message://msg-id-here",
"label": "Open in Mail"
}
},
"execution": {
"executionId": "exec-abc-123",
"workflowId": "wf-456"
}
}
context object is where you put both the data that becomes Request Context (for parameter mapping) and the openLink for external app links. Everything in context is visible to the user when they expand Request Context on the message.
Same as /api/ai/agent-inference but includes full conversation history in the provider request. Use this when a workflow needs the AI to reason about prior messages in the conversation. Takes context.activeAgentId instead of a top-level agentId.
Returns information about the active AI provider and all available providers. No request body required. Useful for workflows that need to know which model is in use or check provider status.
For expected failures (e.g., "email not found"), return an explicit error object from your workflow:
return [{
json: {
error: "Email with UID 456 not found in INBOX",
success: false
}
}];
The AI will report the error to the user in natural language.
Use this checklist when building a new tool workflow:
| Step | |
|---|---|
| ☐ | Workflow starts with a Webhook node (POST, with a path) |
| ☐ | Workflow has a clear, action-oriented name |
| ☐ | Description is set (workflow settings or Sticky Note) |
| ☐ | Code nodes use parameters.x ?? default or body.x || default patterns |
| ☐ | Output uses flat, human-readable field names for key-value rendering |
| ☐ | openLink included if there's a natural source app to link back to |
| ☐ | Error cases return { error: "...", success: false } |
| ☐ | Workflow is published (toggled to Active) |