@awesomate/hosting-mcp
Version:
Awesomate MCP server — lets Claude manage your Awesomate WordPress hosting, plan, limits, n8n automations, and build Node/static apps + databases
144 lines (118 loc) • 7.33 kB
Markdown
# AI Agent / LLM workflows on Awesomate n8n
Read before designing or editing any agent, chat, or LLM-chain workflow.
**Not sure this is the right kind of agent?** An assistant the user sets up
once and talks to in Slack/Telegram, runs on a schedule, or calls from many
workflows is an **n8n Agent** (the Agents tab, n8n 2.40+), not a workflow with
an AI Agent node: read [n8n-agents.md](n8n-agents.md) and use
`awesomate_n8n_agents`.
Platform basics (task runners, `$vars`, `$json.body`) are in platform-notes.md.
## Before building — always
1. Call `awesomate_n8n_context` — confirm consent, plan, variant, limits.
2. Check model credentials FIRST: `awesomate_n8n_inspect {what:"credentials"}`.
Look for openrouter / openai / anthropic entries. No model credential =
stop and ask the user; never invent one.
3. Verify current typeVersions via `awesomate_n8n_node_docs {tool:"get_node"}`
— `agent`, `chatTrigger`, `httpRequestTool` bump frequently. Point-in-time
snapshot (re-verify): `/n8n-nodes-langchain.agent` 3.1,
`n8n-nodes-base.httpRequestTool` 4.4, `lmChatOpenRouter` 1. On 503
`node_catalog_unavailable`, fall back to the vendor/ references.
## Architecture
- Chat agent = `/n8n-nodes-langchain.chatTrigger` →
`/n8n-nodes-langchain.agent`, with model (`ai_languageModel`), memory
(`ai_memory`), and tools (`ai_tool`) attached as sub-node connections.
- Agent v3.x: `systemMessage` lives at `parameters.options.systemMessage`.
The validator reports it missing — false positive, ignore. Set
`options.maxIterations` explicitly.
- Chat Hub / streaming requires agent typeVersion >= 3.x. A 1.x agent behind
a chatTrigger fails at send time with "Agent node version is too old to
support streaming responses".
- **Reasoning/execution separation**: the AI decides, deterministic nodes
act. Validate model output before any side effect. An LLM cannot tell its
input was truncated — detect truncation in the deterministic layer, state
it in the payload, and forbid destructive recommendations explicitly.
## Tools
- HTTP tool node is `n8n-nodes-base.httpRequestTool` at its CURRENT
typeVersion (verify via get_node; 4.4 at last check). NEVER
`/n8n-nodes-langchain.toolHttpRequest` — deprecated, and under agent
v3.x it fails every call with `has a "supplyData" method but no "execute"
method`.
- Every tool needs a descriptive `toolDescription` — it is the only signal
the agent has for choosing and parameterizing the tool.
- Headers via `headerParameters.parameters` `[{name, value}]`; body via
`bodyParameters.parameters`. Full response (status/headers/IDs):
`options.response.response.fullResponse: true`.
### $fromAI rules
- `$fromAI('alias', 'description', 'string')` goes in individual tool
parameter VALUES only: `"value": "={{ $fromAI('alias', 'desc', 'string') }}"`.
- NEVER inside `JSON.stringify()` or embedded mid-string in `jsonBody` — the
`$fromAI` scanner cannot extract it and the model passes literal
placeholder text. (Sole exception: a `jsonBody` that is ONE whole-body
`$fromAI('JSON', ``, 'json')` expression, optionally wrapped in an
arrow-IIFE to inject mandatory fields — keep the
`/*n8n-auto-generated-fromAI-override*/` marker.)
- One `$fromAI` key per node = one parameter. Repeating a key in multiple
parameters with differing description/type crashes EVERY agent turn with
`Duplicate key '<k>' found` before any LLM call.
- Type `'json'` does NOT parse a JSON-encoded string argument. For
array/object params use `JSON.parse($fromAI(..., 'string'))` — the parse
throw surfaces as a tool error the agent recovers from; it is load-bearing.
- Default emitted type is `'string'`. Numeric/boolean params need a manual
override: `={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('limit',
`desc`, 'number') }}` — otherwise real numbers fail schema validation.
### toolWorkflow (sub-workflow tools)
- The sub-workflow must be ACTIVE — an inactive one errors at tool-call
time, not save time.
- `workflowInputs` needs a populated `schema`, not just `value`. With
`schema: []`, `$fromAI` mappings silently resolve to empty strings and the
agent loops to "Max iterations reached".
- Tools run the sub-workflow's PUBLISHED version. Draft edits are dormant
until the sub-workflow is republished — the classic "my edit did nothing".
## Model credentials
- OpenRouter via `lmChatOpenRouter`: model IDs use DOT notation
(`anthropic/claude-sonnet-4.5`), never hyphenated version suffixes — the
wrapper mangles them. Dated slugs (`...-20250929`) are rejected. Verify
slugs against OpenRouter's live `/api/v1/models`, not memory.
- Dedicated model nodes (lmChatOpenRouter etc.) auto-bind credentials by
NAME at create time — prefer them over raw HTTP for LLM calls.
## Memory
- Separate memory per user/session: key the memory node's session on the
chatTrigger's `sessionId`. A static shared key mixes every user's
conversation into one history.
- Motorhead memory node is deprecated — do not use.
## Structured output
- NEVER attach a structured output parser to the FINAL agent of a chat
workflow — it breaks streaming/chat responses. Agent v3.x + parser +
`enableStreaming: true` loops to max iterations: tools fire (side effects
happen) on iteration 1, then the agent restates a valid answer forever.
- Prefer deriving routing metadata deterministically (e.g.
`{{ $('Trigger').isExecuted }}`) over asking the LLM to echo it. If
structured output is genuinely needed, disable streaming or parse in a
downstream node.
- `retryOnFail` on an agent whose tools have side effects re-runs the whole
agent after a post-success failure → duplicate posts/sends. Don't combine.
## chainLlm (Basic LLM Chain)
- Emits NO `pairedItem`: any downstream `$('Node').item` throws "Paired item
data ... is unavailable" on multi-item inputs. `$('Node').first()` works.
Fixes: positional re-join in a Code node right after the chain (with a
count-mismatch guard), or route all items through ONE switch output so the
chain runs exactly once (fan-in from two outputs breaks pairing).
- Its error output (`onError: continueErrorOutput`) DOES carry the input
item's json fields plus an `error` key.
## Chat widget embed (agent on a website)
n8n's chat widget can embed the agent on any site. chatTrigger config:
- `mode: "webhook"` and `responseMode: "lastNode"` for external embedding.
- CORS `allowedOrigins`: no trailing slashes, no spaces after commas.
- No structured output parser on the final agent (see above).
## Test and publish
- E2E = publish + production webhook + poll executions. Publish through the
n8n MCP server, fire the production webhook (or the n8n server's execute
tool), then `awesomate_n8n_executions {workflowId}` to find the run and
`awesomate_n8n_executions {executionId, debug: true}` for node-by-node
detail.
- A change to a live agent workflow goes onto its own id (SKILL.md §4); a
copy mints new webhookIds.
- `saveExecutionProgress` stays FALSE (set it yourself; quadratic-write
incident). Agent/tool loops around `splitInBatches` need an
`executionTimeout`.
- Agent + chat workflows also run their published version — republish after
edits, and republish referenced sub-workflows too.