> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plungeai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents — the registry, discovery, and execution

> An agent is a deployed capability with a uniform interface: it accepts a task, does one job well (search the web, call an LLM, convert a document, post to Slack, enrich a CRM contact), and stores its result where the platform can hand it to the next step.


<!-- sources-of-truth: docs/architecture.md, orchestration/CLAUDE.md (registry), orchestration/mcp-gateway/server.ts, orchestration/api-gateway/openapi.ts, docs/PLUNGE-AI-AGENTS.md | last-synced: 2026-09-24 (re-verified: ~10-20ms RPC overhead claim against docs/architecture.md, GET /v1/agents and /v1/agents/categories shapes against routes/agents.ts — all match, no drift found) -->
An **agent** is a deployed capability with a uniform interface: it accepts a task,
does one job well (search the web, call an LLM, convert a document, post to Slack,
enrich a CRM contact), and stores its result where the platform can hand it to the
next step. Agents are the building blocks everything else composes: workflows chain
them, missions call them, tools are a structured sub-species of them.

The catalog is **live and active-only**: every listed agent is deployed and callable,
and execution refuses any id that is not currently active. That is why ids must come
from a live lookup, never from memory or an example you saw yesterday.

## Two kinds of agent — pick the right execution door

| Kind | How you recognize it | How to execute |
|---|---|---|
| **Prompt-driven** | Card describes free-text input (e.g. `llm-agent`, `skill-agent`, search agents like `brave-agent`, `exa-agent`) | `plungeai_execute_agent` (MCP) or `POST /v1/agents/{id}/execute` (One API) with a `prompt` |
| **Structured tool-agent** | Card carries a **Parameters table** / operations (e.g. document converters, weather, data-table, calendar agents) | Fetch the contract first (`plungeai_get_tool_contract` / `GET /v1/tools/{id}`), then `plungeai_execute_tool` / `POST /v1/tools/{id}/execute` with typed `params` — see the `plungeai-tools-connectors` skill |

Sending prose to a structured agent, or typed fields to a prompt-driven one, is the
most common execution mistake. The agent card tells you which kind you have.

## Terminology trap: "my agents"

Users call their **saved workflows** "agents" too. An unqualified "show me my agents"
means their saved workflows → `plungeai_list_workflows`. The registry
(`plungeai_list_agents`) is the platform capability catalog — building blocks like
`exa-agent` — and is what YOU use when selecting components. Only use the registry
listing when the user explicitly asks about platform capabilities, or when you are
composing.

## Discovery

### MCP: `plungeai_list_agents`

`search` is a **hybrid semantic + keyword** query over live agent cards. Describe the
capability in natural language and trust the ranking:

```
plungeai_list_agents {search: "convert pdf to markdown"}
plungeai_list_agents {search: "web search"}
plungeai_list_agents {category: "financial"}
plungeai_list_agents {agent_id: "exa-agent"}     # full card for one agent
```

- Prefer `search`/`category` filters. An unfiltered listing returns the whole
  catalog (large, slow to read, rarely what you want — discover, don't page through).
- Fetch the **full card** (`agent_id`) before first use of an unfamiliar agent.
  Cards carry: operations, parameters, good-at examples, and — critically —
  **"Not for → use X instead"** redirects that save you a wrong pick.

### One API

```bash
# List active agents (paged)
curl -s "https://api.plungeai.com/v1/agents?limit=20&offset=0" \
  -H "Authorization: Bearer ozk_YOUR_KEY"

# Hybrid search over the whole registry (agents, mcp-servers, …)
curl -s "https://api.plungeai.com/v1/discovery/search?q=web%20search&kind=agents&fields=summary" \
  -H "Authorization: Bearer ozk_YOUR_KEY"

# Ask the platform to recommend the best card for a task
curl -s -X POST https://api.plungeai.com/v1/discovery/recommend \
  -H "Authorization: Bearer ozk_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"type": "agent", "task": "find recent news about a company"}'

# Full card, markdown LLM view
curl -s https://api.plungeai.com/v1/discovery/cards/agent/exa-agent \
  -H "Authorization: Bearer ozk_YOUR_KEY"
```

Search response envelope: `{cards: [...], count, searchMethod}`. Each card carries
`id, name, type, category, status, description, tags`. Add `include=quality` to get
a `quality` block per card (`score`, `success_rate`, `runs` — `null` when unmeasured);
use it to prefer proven agents when several match.

`mode=hybrid|keyword|vector` forces a search leg; the default hybrid is almost always
right — do not re-implement ranking client-side.

## Categories (orientation, not an inventory)

Agents are organized by domain: **search** (Brave, Tavily, Exa, Perplexity, Serper),
**generic LLM** (llm-agent, skill-agent), **documents**, **financial**,
**CRM** (large family: enrichment, outreach, scoring), **coding**, **legal**,
**healthcare**, **logistics**, **marketing**, **market research**, **social**,
**payments**, **e-commerce**, **news**, **travel**, **design**, **automation**,
**Google Workspace** (gmail, calendar, drive), **Microsoft 365**, and more. Category
names are stable; membership is not — discover live.

Stable id shape: kebab-case, usually `<thing>-agent` (`brave-agent`, `exa-agent`,
`llm-agent`). Beware near-misses: `brave-agent` exists, `brave-search` may not — take
the id character-for-character from the search result.

## Execution

### MCP: `plungeai_execute_agent`

```
plungeai_execute_agent {
  agent: "llm-agent",
  prompt: "Summarize the three biggest risks in this text: ...",
  session_id: "optional — start/continue a conversational session"
}
```

- The id parameter is **`agent`** (not `agent_id`, which belongs to the tool-contract
  door). Optional per-call overrides: `persona`, `model`, `maxTokens`.
- Returns a structured outcome. `ok` → the result content (final, user-ready
  markdown — relay verbatim). Anything else names the remediation (see SKILL.md
  "Trust fences").
- `session_id` makes conversational agents stateful across calls.
- **This tool has no `mode` parameter — it is always sync.** For a long single-agent
  run, use the One API with `"sync": false` (below), or run it as a one-task
  workflow via `plungeai_execute_workflow {mode: "async"}` → poll
  `plungeai_get_workflow_status`, fetch with `plungeai_get_result`.

### One API: `POST /v1/agents/{id}/execute`

```bash
curl -s -X POST https://api.plungeai.com/v1/agents/llm-agent/execute \
  -H "Authorization: Bearer ozk_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{
    "prompt": "One-paragraph brief: the current state of solid-state batteries",
    "model": "claude-sonnet-5",
    "maxTokens": 2048,
    "sync": true
  }'
```

Sync response (default):

```json
{
  "content": "…final markdown…",
  "workflow_id": "exec-…",
  "task_id": "…",
  "request_id": "…"
}
```

`input` is an alias for `prompt`; `persona` injects a persona (see the
`plungeai-skills-plugins` skill); `model`/`maxTokens` override per call.

**Async:** `"sync": false` → `202` with `{workflow_id, task_id, request_id}`. Redeem:

```bash
curl -s https://api.plungeai.com/v1/agents/results/{workflowId}/{taskId} \
  -H "Authorization: Bearer ozk_YOUR_KEY"
# 200 {content, content_type, workflow_id, task_id} | 404 {error: {code: "not_ready"}}
```

`404 not_ready` means still running — poll again; it is not a failure.

### Errors you will actually see

| Signal | Meaning | Do |
|---|---|---|
| `400 missing_prompt` | No prompt/input in body | Send one |
| refusal naming the agent as parked/unknown | Id not active in the live catalog | Re-search the registry; take a live id |
| `502 engine_error` / `result_unavailable` | Downstream execution failed | Read the message; check traces (`plungeai-results-traces`); do not hammer-retry |
| Outcome `needs_connection` | Agent needs a user credential (e.g. Google OAuth) | Tell the user what to connect in Studio, then retry |

## Under the hood (why it behaves this way)

Every agent implements the same interface — `executeTask(yaml) → string` over
Cloudflare service-binding RPC — which is what makes agents interchangeable inside
workflows and lets the engine fan them out in parallel with ~10-20 ms dispatch
overhead. Results are written to SharedMemory keyed by `(workflow_id, task_id,
your user id)`, which is why every execution — even a single agent call — hands back
a `workflow_id`/`task_id` pair you can redeem later. See the `plungeai-memory`
skill for retrieval and `plungeai-workflows` for composition.

## Checklist before any agent call

1. Id from a live search (never memory).
2. Full card read if unfamiliar — right kind (prompt vs structured), right agent
   ("Not for" redirects honored).
3. Right door: prompt-driven → execute_agent; structured → contract + execute_tool.
4. Long run → async mode.
5. Outcome remediation followed; fences surfaced, never retried blind.
