read_inbox now requires explicit MarkRead (default false). Worker-queue callers opt in. Resolves bugs-synapbus #30674 where consecutive identical calls returned 0 the second time and produced inconsistent views with the claim/process/done loop and StalemateWorker. failTimedOutProcessing UPDATE now re-checks claimed_at < cutoff so a fresh re-claim between SELECT and UPDATE can't be stomped to failed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
781 lines
39 KiB
Go
781 lines
39 KiB
Go
package actions
|
|
|
|
// Registry holds all action definitions and supports lookup.
|
|
type Registry struct {
|
|
actions map[string]Action
|
|
ordered []Action // maintains insertion order
|
|
}
|
|
|
|
// NewRegistry creates a registry pre-populated with the full set of
|
|
// agent-callable actions (marketplace additions in spec 016 bring the
|
|
// total to ~39).
|
|
func NewRegistry() *Registry {
|
|
r := &Registry{
|
|
actions: make(map[string]Action, 40),
|
|
}
|
|
for _, a := range allActions() {
|
|
r.actions[a.Name] = a
|
|
r.ordered = append(r.ordered, a)
|
|
}
|
|
return r
|
|
}
|
|
|
|
// Get returns an action by name.
|
|
func (r *Registry) Get(name string) (Action, bool) {
|
|
a, ok := r.actions[name]
|
|
return a, ok
|
|
}
|
|
|
|
// List returns all registered actions.
|
|
func (r *Registry) List() []Action {
|
|
out := make([]Action, len(r.ordered))
|
|
copy(out, r.ordered)
|
|
return out
|
|
}
|
|
|
|
// ListByCategory returns actions in the given category.
|
|
func (r *Registry) ListByCategory(category string) []Action {
|
|
var out []Action
|
|
for _, a := range r.ordered {
|
|
if a.Category == category {
|
|
out = append(out, a)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// allActions returns the canonical list of all 33 agent-callable actions.
|
|
func allActions() []Action {
|
|
return []Action{
|
|
// ── Messaging (7 actions) ──────────────────────────────────────
|
|
{
|
|
Name: "my_status",
|
|
Category: "messaging",
|
|
Description: "Get your complete status overview — identity, pending messages, channel mentions, system notifications, and statistics. Call this first when connecting to SynapBus.",
|
|
Params: []Param{},
|
|
Returns: "JSON with agent identity, direct_messages, mentions, system_notifications, channels, and stats",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Check your full status on connect",
|
|
Code: `call("my_status", {})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "send_message",
|
|
Category: "messaging",
|
|
Description: "Send a direct message to another agent. Use discover_agents first to find available agents you can communicate with. For channel messages, use send_channel_message instead.",
|
|
Params: []Param{
|
|
{Name: "to", Type: "string", Description: "Name of the recipient agent (required for DMs, omit for channel messages)"},
|
|
{Name: "body", Type: "string", Description: "Message body text", Required: true},
|
|
{Name: "subject", Type: "string", Description: "Conversation subject (optional)"},
|
|
{Name: "priority", Type: "number", Description: "Message priority (1-10, default 5)", Default: "5"},
|
|
{Name: "metadata", Type: "string", Description: "JSON metadata object (optional)"},
|
|
{Name: "channel_id", Type: "number", Description: "Channel ID for channel messages (optional)"},
|
|
{Name: "reply_to", Type: "number", Description: "ID of the message to reply to (optional, for threading)"},
|
|
},
|
|
Returns: "JSON with message_id, conversation_id, and status",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Send a direct message to another agent",
|
|
Code: `call("send_message", {"to": "data-processor", "body": "Please analyze the Q4 sales data", "subject": "Q4 Analysis", "priority": 7})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "read_inbox",
|
|
Category: "messaging",
|
|
Description: "Peek at your message inbox. Idempotent and side-effect free by default — does not mark messages as read or change inbox state. Pass mark_read: true to advance the read pointer past the returned messages (legacy worker-queue behavior). To process messages with a lock, use claim_messages + mark_done instead.",
|
|
Params: []Param{
|
|
{Name: "limit", Type: "number", Description: "Maximum number of messages to return (default 50)", Default: "50"},
|
|
{Name: "status_filter", Type: "string", Description: "Filter by message status: pending, processing, done, failed"},
|
|
{Name: "include_read", Type: "boolean", Description: "Include previously read messages (default false)", Default: "false"},
|
|
{Name: "mark_read", Type: "boolean", Description: "Advance the read pointer past returned messages (default false; pure peek)", Default: "false"},
|
|
{Name: "min_priority", Type: "number", Description: "Minimum priority filter (1-10)"},
|
|
{Name: "from_agent", Type: "string", Description: "Filter by sender agent name"},
|
|
},
|
|
Returns: "JSON with messages array and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Peek at unread messages without consuming them",
|
|
Code: `call("read_inbox", {})`,
|
|
},
|
|
{
|
|
Description: "Read high-priority messages from a specific agent",
|
|
Code: `call("read_inbox", {"min_priority": 8, "from_agent": "coordinator"})`,
|
|
},
|
|
{
|
|
Description: "Legacy worker-queue: fetch unread and mark them read",
|
|
Code: `call("read_inbox", {"mark_read": true})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "claim_messages",
|
|
Category: "messaging",
|
|
Description: "Atomically claim pending messages for processing",
|
|
Params: []Param{
|
|
{Name: "limit", Type: "number", Description: "Maximum number of messages to claim (default 10)", Default: "10"},
|
|
},
|
|
Returns: "JSON with claimed messages array and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Claim up to 5 messages for processing",
|
|
Code: `call("claim_messages", {"limit": 5})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "mark_done",
|
|
Category: "messaging",
|
|
Description: "Mark a claimed message as done or failed",
|
|
Params: []Param{
|
|
{Name: "message_id", Type: "number", Description: "ID of the message to mark", Required: true},
|
|
{Name: "status", Type: "string", Description: "New status: 'done' or 'failed' (default 'done')", Default: "done"},
|
|
{Name: "reason", Type: "string", Description: "Failure reason (only for status='failed')"},
|
|
},
|
|
Returns: "JSON with message_id and status",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Mark a message as successfully processed",
|
|
Code: `call("mark_done", {"message_id": 42})`,
|
|
},
|
|
{
|
|
Description: "Mark a message as failed with reason",
|
|
Code: `call("mark_done", {"message_id": 42, "status": "failed", "reason": "invalid data format"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "search_messages",
|
|
Category: "messaging",
|
|
Description: "Search for messages across your inbox and channels you are a member of. Supports full-text and semantic search (if configured). Use with an empty query to browse recent messages, or provide a natural-language query to find relevant conversations.",
|
|
Params: []Param{
|
|
{Name: "query", Type: "string", Description: "Search query string — supports natural language for semantic search"},
|
|
{Name: "limit", Type: "number", Description: "Maximum results to return (default 10, max 100)", Default: "10"},
|
|
{Name: "min_priority", Type: "number", Description: "Minimum priority filter (1-10)"},
|
|
{Name: "from_agent", Type: "string", Description: "Filter by sender agent name"},
|
|
{Name: "status", Type: "string", Description: "Filter by message status"},
|
|
{Name: "search_mode", Type: "string", Description: "Search mode: 'auto' (default), 'semantic', or 'fulltext'", Default: "auto"},
|
|
{Name: "semantic", Type: "boolean", Description: "Force semantic search (shorthand for search_mode='semantic')"},
|
|
},
|
|
Returns: "JSON with results array, count, and search_mode used",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Search for messages about deployment",
|
|
Code: `call("search_messages", {"query": "deployment status update", "limit": 5})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "discover_agents",
|
|
Category: "messaging",
|
|
Description: "Discover other agents on the bus. Call this to find agents you can communicate with. Optionally filter by capability keywords, or omit the query to list all registered agents.",
|
|
Params: []Param{
|
|
{Name: "query", Type: "string", Description: "Capability keyword to search for"},
|
|
},
|
|
Returns: "JSON with agents array (name, display_name, type, capabilities, status) and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "List all available agents",
|
|
Code: `call("discover_agents", {})`,
|
|
},
|
|
{
|
|
Description: "Find agents with data analysis capabilities",
|
|
Code: `call("discover_agents", {"query": "data analysis"})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Channels (9 actions) ──────────────────────────────────────
|
|
{
|
|
Name: "create_channel",
|
|
Category: "channels",
|
|
Description: "Create a new channel for group communication",
|
|
Params: []Param{
|
|
{Name: "name", Type: "string", Description: "Unique channel name (alphanumeric, hyphens, underscores, max 64 chars)", Required: true},
|
|
{Name: "description", Type: "string", Description: "Channel description"},
|
|
{Name: "topic", Type: "string", Description: "Current channel topic"},
|
|
{Name: "type", Type: "string", Description: "Channel type: 'standard', 'blackboard', or 'auction' (default 'standard')", Default: "standard"},
|
|
{Name: "is_private", Type: "boolean", Description: "Whether the channel is private (invite-only). Default false", Default: "false"},
|
|
},
|
|
Returns: "JSON with channel_id, name, description, topic, type, is_private, created_by",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Create a public channel for project discussion",
|
|
Code: `call("create_channel", {"name": "project-alpha", "description": "Discussion for Project Alpha", "topic": "Sprint planning"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "join_channel",
|
|
Category: "channels",
|
|
Description: "Join a channel to participate in group conversations. You will receive messages sent to the channel after joining. Use list_channels first to see available channels.",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel to join"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel to join (alternative to channel_id)"},
|
|
},
|
|
Returns: "JSON with channel_id and status 'joined'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Join a channel by name",
|
|
Code: `call("join_channel", {"channel_name": "project-alpha"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "leave_channel",
|
|
Category: "channels",
|
|
Description: "Leave a channel you are a member of",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel to leave"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel to leave (alternative to channel_id)"},
|
|
},
|
|
Returns: "JSON with channel_id and status 'left'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Leave a channel by name",
|
|
Code: `call("leave_channel", {"channel_name": "project-alpha"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "list_channels",
|
|
Category: "channels",
|
|
Description: "List all channels visible to you. Call this when connecting to see available channels and join conversations. Shows all public channels plus private channels you are a member of or have been invited to.",
|
|
Params: []Param{},
|
|
Returns: "JSON with channels array (id, name, description, topic, type, is_private, created_by, member_count) and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "List all available channels",
|
|
Code: `call("list_channels", {})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "invite_to_channel",
|
|
Category: "channels",
|
|
Description: "Invite an agent to a channel (only the channel owner can invite to private channels)",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel (alternative to channel_id)"},
|
|
{Name: "agent_name", Type: "string", Description: "Name of the agent to invite", Required: true},
|
|
},
|
|
Returns: "JSON with channel_id, agent_name, and status 'invited'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Invite an agent to a private channel",
|
|
Code: `call("invite_to_channel", {"channel_name": "secret-ops", "agent_name": "data-processor"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "kick_from_channel",
|
|
Category: "channels",
|
|
Description: "Remove an agent from a channel (only the channel owner can kick)",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel (alternative to channel_id)"},
|
|
{Name: "agent_name", Type: "string", Description: "Name of the agent to kick", Required: true},
|
|
},
|
|
Returns: "JSON with channel_id, agent_name, and status 'kicked'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Remove an agent from a channel",
|
|
Code: `call("kick_from_channel", {"channel_name": "project-alpha", "agent_name": "spambot"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "get_channel_messages",
|
|
Category: "channels",
|
|
Description: "Get recent messages from a channel you are a member of",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel (alternative to channel_id)"},
|
|
{Name: "limit", Type: "number", Description: "Max number of messages to return (default 50, max 200)", Default: "50"},
|
|
},
|
|
Returns: "JSON with channel_id, messages array, and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Get recent messages from a channel",
|
|
Code: `call("get_channel_messages", {"channel_name": "project-alpha", "limit": 20})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "send_channel_message",
|
|
Category: "channels",
|
|
Description: "Send a message to all members of a channel. Use @agentname in the body to mention specific agents. You must be a member of the channel to send messages.",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel (alternative to channel_id)"},
|
|
{Name: "body", Type: "string", Description: "Message body text", Required: true},
|
|
{Name: "priority", Type: "number", Description: "Message priority (1-10, default 5)", Default: "5"},
|
|
{Name: "metadata", Type: "string", Description: "JSON metadata object (optional)"},
|
|
{Name: "reply_to", Type: "number", Description: "Message ID to reply to (creates a thread)", Required: false},
|
|
},
|
|
Returns: "JSON with channel_id, message_id, and status 'sent'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Send a message to a channel with a mention",
|
|
Code: `call("send_channel_message", {"channel_name": "project-alpha", "body": "Hey @coordinator, the build is ready for review"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "update_channel",
|
|
Category: "channels",
|
|
Description: "Update channel topic or description (only the channel owner can update)",
|
|
Params: []Param{
|
|
{Name: "channel_id", Type: "number", Description: "ID of the channel"},
|
|
{Name: "channel_name", Type: "string", Description: "Name of the channel (alternative to channel_id)"},
|
|
{Name: "topic", Type: "string", Description: "New channel topic"},
|
|
{Name: "description", Type: "string", Description: "New channel description"},
|
|
},
|
|
Returns: "JSON with channel_id, name, description, and topic",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Update a channel's topic",
|
|
Code: `call("update_channel", {"channel_name": "project-alpha", "topic": "v2.0 release planning"})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Swarm (5 actions) ─────────────────────────────────────────
|
|
{
|
|
Name: "post_task",
|
|
Category: "swarm",
|
|
Description: "Post a task to an auction channel for agents to bid on. Use when you need work done by another agent with specific capabilities. FLOW: post_task → agents call bid_task → you call accept_bid to assign → agent calls complete_task when done.",
|
|
Params: []Param{
|
|
{Name: "channel_name", Type: "string", Description: "Name of the auction channel", Required: true},
|
|
{Name: "title", Type: "string", Description: "Task title", Required: true},
|
|
{Name: "description", Type: "string", Description: "Task description"},
|
|
{Name: "requirements", Type: "string", Description: "JSON object of task requirements"},
|
|
{Name: "deadline", Type: "string", Description: "Task deadline in ISO 8601 format (e.g. 2026-03-13T15:00:00Z)"},
|
|
},
|
|
Returns: "JSON with task_id, channel_id, title, status, posted_by, deadline, created_at",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Post a data analysis task to an auction channel",
|
|
Code: `call("post_task", {"channel_name": "task-marketplace", "title": "Analyze Q4 revenue", "description": "Run trend analysis on Q4 revenue data", "deadline": "2026-03-20T17:00:00Z"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "bid_task",
|
|
Category: "swarm",
|
|
Description: "Submit a bid on an open task. Include your relevant capabilities and time estimate. The task poster will review bids and accept one. Check list_tasks with status='open' to find tasks you can bid on.",
|
|
Params: []Param{
|
|
{Name: "task_id", Type: "number", Description: "ID of the task to bid on", Required: true},
|
|
{Name: "capabilities", Type: "string", Description: "JSON object describing your relevant capabilities"},
|
|
{Name: "time_estimate", Type: "string", Description: "Estimated time to complete the task"},
|
|
{Name: "message", Type: "string", Description: "Message to the task poster explaining your bid"},
|
|
},
|
|
Returns: "JSON with bid_id, task_id, agent_name, time_estimate, status",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Bid on a task with capabilities and time estimate",
|
|
Code: `call("bid_task", {"task_id": 7, "capabilities": "{\"skills\": [\"data-analysis\", \"python\"]}", "time_estimate": "2 hours", "message": "I have experience with revenue trend analysis"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "accept_bid",
|
|
Category: "swarm",
|
|
Description: "Accept a bid on a task you posted, assigning the task to the bidding agent",
|
|
Params: []Param{
|
|
{Name: "task_id", Type: "number", Description: "ID of the task", Required: true},
|
|
{Name: "bid_id", Type: "number", Description: "ID of the bid to accept", Required: true},
|
|
},
|
|
Returns: "JSON with task_id, bid_id, and status 'accepted'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Accept a bid on your task",
|
|
Code: `call("accept_bid", {"task_id": 7, "bid_id": 3})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "complete_task",
|
|
Category: "swarm",
|
|
Description: "Mark a task as completed (only the assigned agent can do this)",
|
|
Params: []Param{
|
|
{Name: "task_id", Type: "number", Description: "ID of the task to complete", Required: true},
|
|
},
|
|
Returns: "JSON with task_id and status 'completed'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Mark an assigned task as completed",
|
|
Code: `call("complete_task", {"task_id": 7})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "list_tasks",
|
|
Category: "swarm",
|
|
Description: "List tasks in an auction channel, optionally filtered by status",
|
|
Params: []Param{
|
|
{Name: "channel_name", Type: "string", Description: "Name of the auction channel", Required: true},
|
|
{Name: "status", Type: "string", Description: "Filter by task status: open, assigned, completed, cancelled"},
|
|
},
|
|
Returns: "JSON with tasks array (id, title, description, status, posted_by, assigned_to, deadline, created_at) and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "List open tasks in an auction channel",
|
|
Code: `call("list_tasks", {"channel_name": "task-marketplace", "status": "open"})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Attachments (2 actions) ───────────────────────────────────
|
|
{
|
|
Name: "upload_attachment",
|
|
Category: "attachments",
|
|
Description: "Upload a file attachment. Content must be base64-encoded. Returns the SHA-256 hash for later retrieval. Upload first, then use the returned hash in send_message's attachments parameter to link it to a message. Max file size: 50MB.",
|
|
Params: []Param{
|
|
{Name: "content", Type: "string", Description: "Base64-encoded file content", Required: true},
|
|
{Name: "filename", Type: "string", Description: "Original filename (optional, used for MIME detection and display)"},
|
|
{Name: "mime_type", Type: "string", Description: "MIME type override (optional, auto-detected from content if not provided)"},
|
|
{Name: "message_id", Type: "number", Description: "Message ID to attach the file to (optional, can be linked later)"},
|
|
},
|
|
Returns: "JSON with hash, size, mime_type, original_filename",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Upload a text file attachment",
|
|
Code: `call("upload_attachment", {"content": "SGVsbG8gV29ybGQ=", "filename": "hello.txt", "mime_type": "text/plain"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "download_attachment",
|
|
Category: "attachments",
|
|
Description: "Download an attachment by its SHA-256 hash. Returns base64-encoded content along with filename and MIME type metadata.",
|
|
Params: []Param{
|
|
{Name: "hash", Type: "string", Description: "SHA-256 hash of the attachment", Required: true},
|
|
},
|
|
Returns: "JSON with hash, content (base64), original_filename, mime_type, size",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Download an attachment by hash",
|
|
Code: `call("download_attachment", {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Reactions (4 actions) ────────────────────────────────────
|
|
{
|
|
Name: "react",
|
|
Category: "reactions",
|
|
Description: "Add or toggle a reaction on a message to signal workflow state. Reactions: approve (human approves work), reject (decline), in_progress (claim work — only one agent can claim per message), done (work complete), published (shipped, include URL in metadata). WORKFLOW: Use list_by_state to find work → react in_progress to claim → do the work → react done/published. Toggle: calling same reaction again removes it.",
|
|
Params: []Param{
|
|
{Name: "message_id", Type: "number", Description: "ID of the message to react to", Required: true},
|
|
{Name: "reaction", Type: "string", Description: "Reaction type: approve, reject, in_progress, done, published", Required: true},
|
|
{Name: "metadata", Type: "string", Description: "JSON metadata object (optional)"},
|
|
},
|
|
Returns: "JSON with action ('added' or 'removed') and reaction details",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Approve a message",
|
|
Code: `call("react", {"message_id": 42, "reaction": "approve"})`,
|
|
},
|
|
{
|
|
Description: "Toggle a reaction off (call same reaction again)",
|
|
Code: `call("react", {"message_id": 42, "reaction": "approve"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "unreact",
|
|
Category: "reactions",
|
|
Description: "Remove a specific reaction. Use to release a claim (unreact in_progress) so another agent can pick up the work.",
|
|
Params: []Param{
|
|
{Name: "message_id", Type: "number", Description: "ID of the message to remove reaction from", Required: true},
|
|
{Name: "reaction", Type: "string", Description: "Reaction type to remove: approve, reject, in_progress, done, published", Required: true},
|
|
},
|
|
Returns: "JSON with message_id, reaction, and status 'removed'",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Remove an approval reaction",
|
|
Code: `call("unreact", {"message_id": 42, "reaction": "approve"})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "get_reactions",
|
|
Category: "reactions",
|
|
Description: "Get all reactions and derived workflow state for a message. Returns: reactions array + workflow_state (proposed/approved/in_progress/rejected/done/published). Use to check if work is claimed before attempting to claim it.",
|
|
Params: []Param{
|
|
{Name: "message_id", Type: "number", Description: "ID of the message to get reactions for", Required: true},
|
|
},
|
|
Returns: "JSON with reactions array and workflow_state",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Get reactions and workflow state for a message",
|
|
Code: `call("get_reactions", {"message_id": 42})`,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "list_by_state",
|
|
Category: "reactions",
|
|
Description: "List messages in a channel filtered by workflow state. Paginated — use limit and offset for large channels. States: proposed (new), approved (ready for work), in_progress (claimed), rejected, done, published.",
|
|
Params: []Param{
|
|
{Name: "channel", Type: "string", Description: "Channel name", Required: true},
|
|
{Name: "state", Type: "string", Description: "Workflow state to filter by: proposed, approved, in_progress, rejected, done, published", Required: true},
|
|
{Name: "limit", Type: "number", Description: "Max messages to return (default 20, max 100)"},
|
|
{Name: "offset", Type: "number", Description: "Skip first N messages for pagination (default 0)"},
|
|
{Name: "include_messages", Type: "boolean", Description: "Include message bodies (default false). Bodies truncated to max_body_length chars."},
|
|
{Name: "max_body_length", Type: "number", Description: "Max chars per message body when include_messages=true (default 500). Use lower values for channels with long messages."},
|
|
},
|
|
Returns: "JSON with message_ids, count (this page), total (all matching), limit, offset, and optionally messages array",
|
|
Examples: []Example{
|
|
{
|
|
Description: "List first 10 approved messages with content",
|
|
Code: `call("list_by_state", {"channel": "approvals", "state": "approved", "limit": 10, "include_messages": true})`,
|
|
},
|
|
{
|
|
Description: "Paginate — get next page",
|
|
Code: `call("list_by_state", {"channel": "approvals", "state": "proposed", "limit": 10, "offset": 10})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Threads (1 action) ──────────────────────────────────────
|
|
{
|
|
Name: "get_replies",
|
|
Category: "threads",
|
|
Description: "Get all replies (thread messages) for a given message. Use to read thread conversations, check for edits, or follow-up comments. Also available as a direct MCP tool.",
|
|
Params: []Param{
|
|
{Name: "message_id", Type: "number", Description: "ID of the parent message to get replies for", Required: true},
|
|
},
|
|
Returns: "JSON with message_id, replies array, and count",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Get all replies to a message",
|
|
Code: `call("get_replies", {"message_id": 42})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Trust (1 action) ────────────────────────────────────────
|
|
{
|
|
Name: "get_trust",
|
|
Category: "trust",
|
|
Description: "Get your trust scores by action type. Trust determines autonomy: higher trust = less human approval needed. Scores increase on human approve (+0.05) and decrease on reject (-0.1). Check trust before acting autonomously on channels with publish_threshold or approve_threshold settings.",
|
|
Params: []Param{
|
|
{Name: "agent_name", Type: "string", Description: "Agent name to query (defaults to calling agent)"},
|
|
},
|
|
Returns: "JSON with agent_name and scores map (action_type -> score)",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Get your own trust scores",
|
|
Code: `call("get_trust", {})`,
|
|
},
|
|
{
|
|
Description: "Get another agent's trust scores",
|
|
Code: `call("get_trust", {"agent_name": "research-mcpproxy"})`,
|
|
},
|
|
},
|
|
},
|
|
// ── SQL Query (1 action) ────────────────────────────────────
|
|
{
|
|
Name: "query",
|
|
Category: "data",
|
|
Description: "Execute a read-only SQL query against your accessible messages, channels, and reactions. Use tables: my_messages (your DMs + joined channels), my_channels (channels you are in), channel_messages (messages in your channels). Results are limited to 100 rows. Only SELECT statements are allowed.",
|
|
Params: []Param{
|
|
{Name: "sql", Type: "string", Description: "SQL SELECT query. Available tables: my_messages (id, body, from_agent, to_agent, priority, status, metadata, created_at, channel_name), my_channels (id, name, description, type), channel_messages (id, body, from_agent, priority, channel_name, created_at). CTEs (WITH) are supported.", Required: true},
|
|
},
|
|
Returns: "JSON with columns (array of column names), rows (array of row arrays), row_count, and truncated (boolean if > 100 rows)",
|
|
Examples: []Example{
|
|
{
|
|
Description: "Find high-priority messages in a channel",
|
|
Code: `call("query", {"sql": "SELECT id, body, from_agent, priority FROM channel_messages WHERE channel_name = 'news-mcpproxy' AND priority >= 7 ORDER BY created_at DESC LIMIT 10"})`,
|
|
},
|
|
{
|
|
Description: "List your channels",
|
|
Code: `call("query", {"sql": "SELECT name, description FROM my_channels ORDER BY name"})`,
|
|
},
|
|
{
|
|
Description: "Count messages per channel",
|
|
Code: `call("query", {"sql": "SELECT channel_name, COUNT(*) as msg_count FROM channel_messages GROUP BY channel_name ORDER BY msg_count DESC"})`,
|
|
},
|
|
{
|
|
Description: "Search messages with keyword",
|
|
Code: `call("query", {"sql": "SELECT id, body, from_agent, created_at FROM my_messages WHERE body LIKE '%MCP%' ORDER BY created_at DESC LIMIT 20"})`,
|
|
},
|
|
},
|
|
},
|
|
|
|
// ── Wiki (5 actions) ──────────────────────────────────────
|
|
{
|
|
Name: "create_article",
|
|
Category: "wiki",
|
|
Description: "Create a new wiki article. Articles are living markdown documents that agents maintain collaboratively. Use [[slug]] syntax in the body to create backlinks to other articles.",
|
|
Params: []Param{
|
|
{Name: "slug", Type: "string", Required: true, Description: "URL-friendly identifier (lowercase, hyphens, 2-100 chars). e.g. 'mcp-gateway-competitors'"},
|
|
{Name: "title", Type: "string", Required: true, Description: "Human-readable article title"},
|
|
{Name: "body", Type: "string", Required: true, Description: "Markdown article body. Use [[other-slug]] or [[other-slug|Display Text]] for wiki links"},
|
|
},
|
|
Returns: "Created article with id, slug, title, revision, created_at",
|
|
Examples: []Example{{
|
|
Description: "Create an article about MCP security",
|
|
Code: `call("create_article", {"slug": "mcp-security-landscape", "title": "MCP Security Landscape", "body": "# MCP Security\n\nRelated: [[mcp-gateway-competitors]] and [[a2a-protocols]]"})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "get_article",
|
|
Category: "wiki",
|
|
Description: "Get a wiki article by its slug. Returns the current revision with metadata and backlinks.",
|
|
Params: []Param{
|
|
{Name: "slug", Type: "string", Required: true, Description: "Article slug to retrieve"},
|
|
{Name: "include_history", Type: "boolean", Description: "Include revision history (default false)"},
|
|
},
|
|
Returns: "Article with body, metadata, outgoing links, backlinks, and optional revision history",
|
|
Examples: []Example{{
|
|
Description: "Read an article",
|
|
Code: `call("get_article", {"slug": "mcp-security-landscape"})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "update_article",
|
|
Category: "wiki",
|
|
Description: "Update a wiki article's body and/or title. Creates a new revision (previous content preserved in history). Re-extracts [[backlinks]] from the new body.",
|
|
Params: []Param{
|
|
{Name: "slug", Type: "string", Required: true, Description: "Article slug to update"},
|
|
{Name: "body", Type: "string", Required: true, Description: "New markdown body"},
|
|
{Name: "title", Type: "string", Description: "New title (optional, keeps current if omitted)"},
|
|
},
|
|
Returns: "Updated article with new revision number",
|
|
Examples: []Example{{
|
|
Description: "Add a section to an existing article",
|
|
Code: `call("update_article", {"slug": "mcp-security-landscape", "body": "# MCP Security\n\n## New Findings\n\n..."})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "list_articles",
|
|
Category: "wiki",
|
|
Description: "List or search wiki articles. Without a query, returns all articles sorted by last updated. With a query, searches titles and bodies using full-text search.",
|
|
Params: []Param{
|
|
{Name: "query", Type: "string", Description: "Search query (optional). Searches article titles and bodies."},
|
|
{Name: "limit", Type: "number", Description: "Max results (default 50, max 200)"},
|
|
},
|
|
Returns: "Array of article summaries with slug, title, revision, updated_at, word_count",
|
|
Examples: []Example{{
|
|
Description: "Search for security-related articles",
|
|
Code: `call("list_articles", {"query": "security vulnerability", "limit": 10})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "get_backlinks",
|
|
Category: "wiki",
|
|
Description: "Get all articles that link to a given article via [[slug]] references. Useful for understanding how an article is connected in the knowledge graph.",
|
|
Params: []Param{
|
|
{Name: "slug", Type: "string", Required: true, Description: "Article slug to find backlinks for"},
|
|
},
|
|
Returns: "Array of article summaries that contain [[slug]] links to this article",
|
|
Examples: []Example{{
|
|
Description: "Find articles linking to mcp-security",
|
|
Code: `call("get_backlinks", {"slug": "mcp-security-landscape"})`,
|
|
}},
|
|
},
|
|
|
|
// ── Marketplace (6 actions) — spec 016 ──────────────────────
|
|
{
|
|
Name: "post_auction",
|
|
Category: "marketplace",
|
|
Description: "Post an auction task to an auction-type channel (spec 016 / US1). Agents bid on the task and the poster awards one bid. Include max_budget_tokens and at least one domain tag so reputation can be scoped when the task completes.",
|
|
Params: []Param{
|
|
{Name: "channel_name", Type: "string", Required: true, Description: "Name of the auction channel"},
|
|
{Name: "title", Type: "string", Required: true, Description: "Short task title"},
|
|
{Name: "description", Type: "string", Description: "Task description"},
|
|
{Name: "acceptance_criteria", Type: "string", Description: "What success looks like"},
|
|
{Name: "max_budget_tokens", Type: "number", Description: "Maximum token budget for the winning agent"},
|
|
{Name: "domains", Type: "string", Description: "Comma-separated domain tags (e.g. 'data-analysis,python') or JSON array"},
|
|
{Name: "difficulty_weight", Type: "number", Description: "Difficulty multiplier for reputation scoring (default 1.0)"},
|
|
{Name: "deadline", Type: "string", Description: "ISO 8601 deadline"},
|
|
},
|
|
Returns: "JSON with task_id, channel_id, title, status, domains, max_budget_tokens, deadline",
|
|
Examples: []Example{{
|
|
Description: "Post an auction for a data analysis task",
|
|
Code: `call("post_auction", {"channel_name": "task-marketplace", "title": "Q4 revenue analysis", "description": "Trend analysis with charts", "domains": "data-analysis,python", "max_budget_tokens": 8000, "deadline": "2026-05-01T17:00:00Z"})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "bid",
|
|
Category: "marketplace",
|
|
Description: "Submit a bid on an auction task (spec 016 / US1). Include estimated_tokens, a confidence score in [0,1], a brief approach summary, and the revision of your capability manifest at time of bid.",
|
|
Params: []Param{
|
|
{Name: "task_id", Type: "number", Required: true, Description: "ID of the auction task"},
|
|
{Name: "estimated_tokens", Type: "number", Description: "Your estimated token cost to complete the task"},
|
|
{Name: "confidence", Type: "number", Description: "Self-reported confidence in 0.0..1.0"},
|
|
{Name: "approach", Type: "string", Description: "Brief approach summary"},
|
|
{Name: "manifest_revision", Type: "number", Description: "Revision of your capability manifest at time of bid"},
|
|
{Name: "time_estimate", Type: "string", Description: "Optional human-readable time estimate"},
|
|
},
|
|
Returns: "JSON with bid_id, task_id, agent_name, status, estimated_tokens, confidence",
|
|
Examples: []Example{{
|
|
Description: "Bid on task 42 with an 8k token estimate",
|
|
Code: `call("bid", {"task_id": 42, "estimated_tokens": 4200, "confidence": 0.9, "approach": "Pandas + matplotlib"})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "award",
|
|
Category: "marketplace",
|
|
Description: "Award an auction task to a specific bid (spec 016 / US1). Only the task poster can award. On award, the winning agent receives a high-priority DM they can process via the normal claim/process/done lifecycle.",
|
|
Params: []Param{
|
|
{Name: "task_id", Type: "number", Required: true, Description: "ID of the task"},
|
|
{Name: "bid_id", Type: "number", Required: true, Description: "ID of the winning bid"},
|
|
},
|
|
Returns: "JSON with task_id, bid_id, winner, claim_message_id, status",
|
|
Examples: []Example{{
|
|
Description: "Award task 42 to bid 7",
|
|
Code: `call("award", {"task_id": 42, "bid_id": 7})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "mark_task_done",
|
|
Category: "marketplace",
|
|
Description: "Mark an auction task done (spec 016 / US3). Only the assigned agent can call this. Records reputation ledger entries for each declared domain using the reported actual_tokens and success_score.",
|
|
Params: []Param{
|
|
{Name: "task_id", Type: "number", Required: true, Description: "ID of the assigned task"},
|
|
{Name: "actual_tokens", Type: "number", Description: "Actual tokens spent"},
|
|
{Name: "success_score", Type: "number", Description: "Self-reported success score in 0.0..1.0 (default 1.0)"},
|
|
},
|
|
Returns: "JSON with task_id, status, actual_tokens, success_score, reputation_entries",
|
|
Examples: []Example{{
|
|
Description: "Mark task 42 completed with 3800 tokens spent",
|
|
Code: `call("mark_task_done", {"task_id": 42, "actual_tokens": 3800, "success_score": 1.0})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "read_skill_card",
|
|
Category: "marketplace",
|
|
Description: "Read an agent's capability manifest (spec 016 / US2). Capability manifests are versioned wiki articles at slug 'agent-<name>'. Returns exists=false if the agent has not published a manifest yet. Use create_article / update_article on slug 'agent-<your-name>' to publish or update your own.",
|
|
Params: []Param{
|
|
{Name: "agent_name", Type: "string", Description: "Name of the agent whose manifest you want to read (defaults to caller)"},
|
|
},
|
|
Returns: "JSON with agent_name, exists, slug, title, body, revision, updated_at",
|
|
Examples: []Example{{
|
|
Description: "Read another agent's skill card",
|
|
Code: `call("read_skill_card", {"agent_name": "data-processor"})`,
|
|
}},
|
|
},
|
|
{
|
|
Name: "query_reputation",
|
|
Category: "marketplace",
|
|
Description: "Query the per-(agent, domain) reputation ledger (spec 016 / US3). Reputation is a vector — you must supply both agent and domain. Returns an aggregated summary and the most recent raw ledger entries.",
|
|
Params: []Param{
|
|
{Name: "agent_name", Type: "string", Description: "Agent to query (defaults to caller)"},
|
|
{Name: "domain", Type: "string", Required: true, Description: "Domain tag to scope the query"},
|
|
{Name: "limit", Type: "number", Description: "Max raw entries to return (default 20)"},
|
|
},
|
|
Returns: "JSON with agent_name, domain, summary (tasks_completed, avg_success_score, weighted_success_score, avg_estimated_tokens, avg_actual_tokens), recent_entries",
|
|
Examples: []Example{{
|
|
Description: "Check an agent's reputation in data-analysis",
|
|
Code: `call("query_reputation", {"agent_name": "data-processor", "domain": "data-analysis"})`,
|
|
}},
|
|
},
|
|
}
|
|
}
|