developer
Use this agent for any n8n development task - frontend (Vue 3), backend (Node.js/TypeScript), workflow engine, node creation, or full-stack features. The agent…
This guide explains how to add chat platform integration tests for agent channel integrations. The current suite covers three layers:
$ npx -y skills add n8n-io/n8n --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
This guide explains how to add chat platform integration tests for agent channel integrations. The current suite covers three layers:
This guide explains how to add chat platform integration tests for agent channel integrations. The current suite covers three layers:
These tests validate n8n's integration logic: routing inbound messages to the agent, preserving message context, executing integration actions, resuming suspended tool calls, and avoiding self-trigger loops.
These tests run the **real** `@chat-adapter/*` adapters and the real `chat` SDK. There are no fake or in-memory adapters. The packages are ESM-only; in production they are loaded via `esm-loader`'s `new Function()` indirection to survive the CJS transform, but **that indirection cannot run under Vitest** — so the test helpers import them directly (`await import('@chat-adapter/telegram')`), which Vitest loads natively. Any test that drives a code path which itself calls `esm-loader` (e.g. the real `ComponentMapper` for rich cards) must `vi.mock('../esm-loader', …)` to redirect the loaders to native dynamic imports — see the telegram tests for the pattern.
The only thing faked is the **external platform HTTP at the network boundary** — you cannot call live Telegram/Slack/Linear from CI. Everything else (adapter, `AgentChatBridge`, integration implementation, action executor, message-context service) is real.
Each platform adapter uses a different HTTP client, so the interception mechanism differs:
| Platform | Adapter HTTP client | Interception | Helper | |----------|---------------------|--------------|--------| | Telegram | native `fetch` | replace `globalThis.fetch` | `installFetchStub` (replay-test-helpers) | | Slack | `@slack/web-api` (axios) | `nock` at the HTTP layer | inline in slack `replay-test-context` | | Linear | `@linear/sdk` (GraphQL over fetch) | replace `globalThis.fetch` | `installFetchStub` |
Responses are answered from two sources, in order of preference:
1. **Recorded data** where it matters — the captured webhook payload is replayed into the real adapter as the inbound event, and recorded outbound bodies inform assertions. 2. **Minimal stubs** for incidental calls the recordings don't need to pin down — identity bootstrap (`getMe`, `auth.test`, Linear `viewer`), streaming lifecycle, and entity look-ups.
The assertions check what the adapter **sends** (the outbound request body), not what it receives, so response stubs only need to be valid enough for the real adapter to proceed.
returns a minimal message. `reply_markup` is sent as a JSON object (not a stringified blob), so read inline-keyboard callback data via `getTelegramInlineCallbackData`.
(`chat.startStream` → `appendStream` → `stopStream`), not `chat.postMessage`. The nock handler reconstructs the streamed text and records it as a synthetic `chat.postMessage` so assertions can treat the reply as one outbound post. `webhookVerifier: () => true` bypasses signature checks (the fixtures carry sanitized signatures); passing `botUserId` skips the `auth.test` lookup.
refreshes `webhookTimestamp` and signs the body. `@linear/sdk` strictly deserializes typed entities and lazily fetches relationships, so the GraphQL stub returns fully-shaped entities (e.g. a `Comment` needs `reactions: []`; an `AgentActivity` references `agentSession`/`sourceComment` by id). Linear's "mention" is an **agent-session** event, not a comment — see the contract note below.
src/modules/agents/integrations/ __tests__/channel-integration-contract.test.ts __tests__/fixtures/<platform>/ __tests__/helpers/<platform>/replay-test-context.ts __tests__/helpers/<platform>/synthetic-fixtures.ts __tests__/helpers/replay-test-helpers.ts # shared: createReplayContextSetup, installFetchStub, … platforms/__tests__/<platform>/recorded-integration.test.ts platforms/__tests__/<platform>/synthetic-integration.test.ts
Each `<platform>/replay-test-context.ts` builds the real adapter + real `Chat`, installs the network interceptor, wires `AgentChatBridge` via `createReplayContextSetup`, and exposes `sendWebhook`, `latestContext`, `lastPost`, `apiCalls`, and `shutdown` (which restores the interceptor).
Use `runSharedChannelIntegrationContract()` when a scenario should behave the same across platforms. It verifies that an integration:
> **Linear is intentionally not in the shared contract.** The real `@chat-adapter/linear` only treats > agent-session events as mentions (a bare comment has `isMention = false`), and agent-session vs > comment threads don't share an id — so the comment-as-mention + subscribe/follow-up contract > doesn't model real Linear behavior. Linear's real flow is covered by its recorded agent-session > test (`platforms/__tests__/linear/recorded-integration.test.ts`).
Assert the real adapter's actual output, not a simplified shape. For example, the message-context `channelId` is platform-prefixed (`telegram:123456`, `slack:C_SUPPORT`), and Slack agent replies are recorded with a `markdown_text` body.
Use synthetic tests for cases that are hard to capture reliably or need narrow edge-case co
Fair-code platform to build and deploy AI agents and workflows. Combine a visual canvas with custom code, run it self-hosted or in the cloud, and connect to 1500+ integrations. AI automation you can trust with real work, from prototype to production.
Repo: n8n-io/n8n
Use this agent for any n8n development task - frontend (Vue 3), backend (Node.js/TypeScript), workflow engine, node creation, or full-stack features. The agent…
Use this agent proactively when a Linear issue is created, updated, or needs comprehensive analysis. This agent performs thorough issue investigation and…
`Agent.promptCaching()` generates provider-specific `providerOptions` for Anthropic and OpenAI so callers don't have to hand-write the Vercel AI SDK's raw…