# n8n Agents (the Agents tab): building them from Claude Code

Read before creating, editing, testing or publishing an **n8n Agent**. For an
AI Agent *node* inside a workflow, read [ai-agents.md](ai-agents.md) instead.

## Which kind of "agent" is this?

Four different things get called an agent. Pick before building:

| The user wants… | Build | Tool |
|---|---|---|
| An assistant they set up once and talk to **in Slack, Telegram, Linear, Discord, Teams or n8n chat**, run **on a schedule**, or call from several workflows; it decides its own steps | **n8n Agent** (this file) | `awesomate_n8n_agents` |
| A fixed trigger → steps → result, with an LLM as one step | Workflow with an AI Agent node | `awesomate_n8n_deploy` + [ai-agents.md](ai-agents.md) |
| A website chat that answers ONLY from their content, with citations | Knowledge agent | awesomate-knowledge skill |
| One of Awesomate's ready-made chat agents | Template bundle | `awesomate_n8n_library` |

If the ask is a schedule with repeatable, enumerable steps, it is probably a
workflow. Say so plainly and ask before building the other thing. Never
substitute a Chat Trigger + AI Agent node for a requested n8n Agent.

## How it works on Awesomate

n8n Agents have **no public API**. The only supported way in is the client's
own n8n **instance-level MCP server**, which has its own key, separate from
the n8n API key. The hub keeps that key (encrypted) and relays one allowlisted
tool call at a time, so the key never reaches this machine.

`awesomate_n8n_agents {action:"status"}` FIRST:

- `keyConfigured: false` → send them to **"Set it up for me"** under **n8n
  Agents access** at hub.awesomate.ai/n8n/settings (`setup.steps`). One
  click: the hub switches on their n8n's MCP (a restart of about 20 seconds
  if it was off), connects their owner key and emails them. There is nothing
  to copy. **You cannot do this step for them**: only that click may connect
  a key, so never offer to. When they say it's done, re-check status. If the
  button can't do it on their instance, its message gives the by-hand route
  (`setup.manualSteps`). Never ask them to paste a key into this chat.
- `code: mcp_disabled` → MCP was switched off in their n8n. "Set it up for
  me" switches it back on.
- `code: mcp_key_rejected` → the hub normally re-reads a regenerated key by
  itself. If this still shows, send them to "Set it up for me" again.
- `missingTools` present → their n8n has no Agents module. Do not try to
  work around it; that's an Awesomate support ask.
- `ready: true` → go. Building, testing and publishing agents work on **every
  plan, Essentials included**. `limits` gives the plan's daily caps.

Everything else goes through `{action:"call", tool, arguments}`. The tool
names and arguments are n8n's own, passed through unchanged. **Before calling
a tool whose arguments you haven't seen this session, run
`{action:"describe", tool}`**: it returns n8n's own description and JSON input
schema. Don't guess argument shapes. For example, `call_agent` takes
`{agentId, request:{type:"message", message}}`, not a bare `message`.

## n8n's live guide beats this file

Before the first build in a session call
`{action:"call", tool:"get_agent_builder_reference"}`. It returns n8n's build
guide AND the canonical JSON schema for the agent config, straight from their
instance's version. When it disagrees with anything here or with what you
remember, it wins. Don't guess config fields.

## The build loop

Same discipline as the workflow loop: discovery → design → **approval** →
build → test → wrap-up.

1. **Discovery.** `search_projects` (on most instances it's one personal
   project: use its `id`). `discover_agent_assets {projectId, kind:"models"}`
   gives providers. Then `{kind:"models", provider, credentialId}` checks the
   models a specific credential can reach. `list_credentials` finds the model
   credential. No model credential → stop; they create one in n8n (see the
   credential rules in SKILL.md). `{kind:"workflows"}` lists the workflows
   that can be tools, with `published` and `triggerType`.
2. **Design** in plain words: what it's for, its instructions, which model,
   which tools (existing workflows first), whether it remembers
   conversations, any schedule or channel. Get a yes.
3. **Create.** `create_agent {projectId, name, config}`.
   - If you pass `config` it MUST include `model` (verified: `config.model:
     Invalid input` otherwise) along with `credential` and `instructions`.
   - `model` is `provider/model`, e.g. `openrouter/anthropic/claude-sonnet-4.5`.
     Use an id from `discover_agent_assets`, never a remembered one.
   - `credential` is a credential **id** from `list_credentials`, never secret
     data.
   - Skills, tasks (schedules) and custom tools can't go in the create
     config: they need server-generated ids. Add them with `mutate_agent`
     after.
   - The result carries `agent.id`, `configHash` and `url`.
4. **Edit** with `mutate_agent {agentId, baseConfigHash, operation}`:
   - `operation.type` is one of `config.patch` (RFC 6902 ops,
     e.g. `{op:"add", path:"/tools/-", value:{…}}`), `config.replace`,
     `skill.upsert|delete`, `task.upsert|delete` or `customTool.upsert|delete`.
   - Always pass the **latest** `configHash` (from create, `get_agent`, or the
     previous mutation). A reused hash returns `ok:false, code:"stale_config"`:
     `get_agent`, re-apply to the fresh config, retry. Verified live.
   - Channels (Slack and so on) are NOT config. Use `update_agent_integration`.
5. **Validate.** `validate_agent {agentId}` → fix every error.
   `incompatible_reference` with `no_supported_trigger` means that workflow
   can't be a tool. `not_published` means it must be active first. On Support
   Plus and above, activate it with `awesomate_n8n_deploy {action:"activate"}`
   after the user's yes (the hub's agency-workflow guards apply there). On
   Essentials the client switches it on in n8n themselves.
6. **Test.** `call_agent {agentId, request:{type:"message", message}}` with
   one representative message. To continue the same conversation, pass the
   `sessionId` it returned. Approval-gated tools come back as a pending
   approval: ask the human, then resume with
   `request:{type:"approval", approved, continuation}`. It runs the
   **draft** with **real tools and real credentials**, so tell the user first
   if a tool sends email, posts or writes anything. Counts against the daily
   test-message cap (failed attempts count too). Report what it said and which
   tools it called.
   - A turn can take one to two minutes. The tool waits for it. If it comes
     back `pending` with a `call_id`, or as `409 agent_call_in_progress`, the
     message is still running: collect it with `{action:"result", call_id}`.
     **Never resend the message**, or its real tools run twice.
   - `504 mcp_timeout` means n8n may have finished it anyway. Check the
     agent's chat in n8n (or `get_agent`) before trying again.
7. **Publish only on an explicit yes.** Building, validating and testing
   never imply publishing. Ask: "It's ready as a draft. Want me to switch it
   on?" Then `publish_agent {agentId}`. If it names unpublished workflows,
   relay them and stop.
8. **Wrap-up.** Give the agent `url`, and say what it does, where they can
   talk to it, and that each message is one execution on their plan.

## Workflow tools

The cleanest power move: their existing workflows become the agent's hands,
and the agent never holds any keys.

- The workflow must start with an **Execute Workflow Trigger**
  (`n8n-nodes-base.executeWorkflowTrigger`) and be in the agent's project.
- It must be **active** before the published agent can call it.
- Tool entry: `{ "type": "workflow", "workflow": "<exact workflow name>",
  "name": "snake_case_tool_name", "description": "when to use it" }`. The
  description is the only thing the agent uses to choose the tool, so write
  it like an instruction.
- Need a new tool workflow? Build it with the normal workflow loop
  (`awesomate_n8n_deploy`) first, test it, then attach it.
- A data table is not usable just because it exists. Attach it as a node
  tool (`n8n-nodes-base.dataTable`, found via `search_nodes`).

## Channels (Slack, Telegram, …)

`update_agent_integration` only. Connecting a channel on an agent that's
**already published** connects it immediately, which is outward-facing, so
confirm first. Slack is two calls: the first, with no credential, lists
workspaces or returns a setup code; the second passes the chosen
`managerCredentialId` + `workspaceId`. Relay `installUrl` / `agentUrl` when
n8n returns them, and only call it connected once `get_agent` shows it.
n8n's live guide has the full Slack status-code ladder.

## Calling an agent from a workflow

Use the hidden **Message an Agent** node (`n8n-nodes-base.messageAnAgent`,
verify typeVersion via `awesomate_n8n_node_docs`). Set `agentId` as a
resource locator `{__rl:true, mode:"list", value:"<agentId>"}` and `message`.
It targets the **published** agent and returns `text`,
`structuredOutput`, `toolCalls` and `session`.

## Guard rails (enforced by the hub)

- Only the agent tools and the read-only discovery tools are relayed. n8n's
  workflow-writing MCP tools are NOT. Workflows still go through
  `awesomate_n8n_deploy`, with its drafts, promote and rollback.
- An agent's config cannot attach a workflow Awesomate manages for the client,
  the n8n node, or any node using an n8n API credential (`403
  agent_tool_blocked`): calling the agent would run them. Use one of the
  client's own workflows. If a workflow tool names only the workflow (no
  `workflowId`) and the hub can't confirm which one it is, the write is
  refused with `workflow_ref_unverified`: look it up with `search_workflows`
  and pass its `workflowId` too. Custom code tools and external MCP servers
  are the client's own choice and are not inspected.
- Every action works on every plan, Essentials included.
- `delete_agent` only works on agents created through Claude Code. Agents
  they built in n8n are deleted in n8n. Use `unpublish_agent` to switch one
  off without losing it.
- Daily caps are their own, separate from workflow builds and test fires:
  agent creates and test messages per day (`status` shows `limits`). One test
  message runs at a time per instance.
- n8n only lets MCP touch agents with "available in MCP" switched on. Agents
  created this way have it. An agent they made in the UI won't appear until
  they switch it on in n8n.
- `ok:false` in a response is n8n's own answer. Read `error.code` /
  `error.message` and fix the input instead of retrying the same call.

## Cost, in their words

One message to an agent = one execution on their plan. Tool calls to their
workflows and to sub-agents within that turn don't count extra. Model usage
bills to whichever model credential the agent uses.
