# n8n

**Provisioning agent identity shouldn't require writing a client library.**

No-code teams build entire agent pipelines in n8n — an HTTP Request node here, a Function node there — and hit the same wall the moment an "agent" needs to *be* something on the network: a real address, a DNS name, a policy, an audit trail. Hand-rolling `X-API-Key` headers and Cypher-building in a Function node works, but it's exactly the glue code n8n exists to eliminate. `n8n-nodes-whisper` turns Whisper's control plane into drag-and-drop: register an agent, set its DNS policy, read its activity, revoke it — all as workflow steps, and on self-hosted n8n the agent's *traffic* really leaves from the identity you just minted.

## Install

```
n8n → Settings → Community Nodes → Install → n8n-nodes-whisper
```

Source: [github.com/whisper-sec/whisper-n8n](https://github.com/whisper-sec/whisper-n8n) (MIT). It ships one node, **Whisper**, with ten operations, and is registered `usableAsTool` so an **AI Agent** node in the same workflow can call it directly — an LLM-driven n8n agent that provisions its own identity mid-run.

## Two tiers, per Postel's Law

Like every Whisper integration, the node is designed to be liberal in what it asks of you: two of its ten operations need **no credential at all**, because they only read data that's already public.

| Tier | Operations | Auth |
|---|---|---|
| **Keyless** | Verify Identity, RDAP Lookup | none |
| **Keyed (control plane)** | Register Agent, Create Identity, List Agents, Get Agent, Set Policy, Get Logs, Revoke Agent, Get Egress Config | your own **Whisper API** credential |

The keyed half is not a teaser — it is the actual product. Add a **Whisper API** credential (your `whisper_live_…` key, from [whisper.online/platform](https://whisper.online/platform)) and every write operation — register, policy, revoke — works exactly as it does from the [`whisper` CLI](https://github.com/whisper-sec/whisper-cli) or the [control plane](/docs/control-plane) directly. Nothing is baked into the node; the key lives only in the n8n credential store and travels as the `X-API-Key` header.

## The mechanism: one Cypher verb, two envelope shapes

Every keyed operation the node exposes is a thin wrapper over a single call:

```
POST https://graph.whisper.security/api/query
X-API-Key: whisper_live_…
Content-Type: application/json

{"query": "CALL whisper.agents({op:'register', args:{label:'invoice-bot'}})"}
```

`op` selects the action (`register`, `identity`, `list`, `agent`, `policy`, `logs`, `revoke`, `connect`); `args` is a Cypher map, built deterministically: strings are single-quoted with `'` and `\` doubled (so `Tim O'Reilly` becomes `'Tim O''Reilly'` and can never break out of the literal), numbers and booleans pass through bare, and map keys are emitted **sorted** so the request is byte-stable. The response is a procedure-row table — `{columns:[...], rows:[...]}` — that the node unwraps into a `{ok, status, result, error}` shape before handing it to the next workflow step; a scope error or a missing field comes back as a structured `{type, title, status, detail}` object, never an opaque 500. The full request/response contract — every op, its args, its result columns — is documented in [`CONTROL_API.md`](https://github.com/whisper-sec/whisper-n8n/blob/main/CONTROL_API.md), which each node operation maps to one-to-one.

### With stock tools (no Whisper software)

n8n's own **HTTP Request** node can call the same endpoint with zero custom code — this is what the community node saves you from wiring by hand:

```bash
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_…" -H 'content-type: application/json' \
  -d '{"query":"CALL whisper.agents({op:'"'"'list'"'"', args:{kind:'"'"'agents'"'"'}})"}' \
  | jq '.rows[0].result.rows'
```

### With the Whisper node

Drag **Whisper** onto the canvas → **Operation: List Agents** → **Kind: Agents**, attach the **Whisper API** credential. No header, no JSON escaping, no Cypher string-building — the node's output is already the flattened `{label, fqdn, address, agent, created, state}` array, ready for a **Split In Batches** or **Filter** node downstream.

## A concrete workflow: nightly identity + policy audit

A realistic use of the node needs no code at all:

1. **Cron** trigger, daily at 02:00.
2. **Whisper → List Agents** (`kind: agents`) — pulls the tenant's fleet.
3. **Whisper → Get Logs** per agent (`kind: dns`, `from: -24h`) — recent DNS activity.
4. **Filter** — keep agents with `dns_blocked > 0` (policy is actively rejecting lookups for them).
5. **Whisper → Set Policy** — tighten `block` for a repeat offender, or leave unchanged (an empty **Default Action** reads the policy back without writing).
6. **Slack / Email node** — post the day's summary.

Because every step is the same `whisper.agents` verb under the hood, this is exactly the workflow you'd script with the CLI in a cron job:

```bash
for a in $(whisper agent list --json | jq -r '.[].agent'); do
  whisper agent logs "$a" --kind dns --from -24h --json
done
```

— the node just makes it a workflow, with retries, branching, and Slack notification for free.

## Egress: making the workflow's *traffic* the agent

Provisioning the identity is half the story; the other half is having outbound HTTP Request calls actually source from the agent's routable `/128` (`2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4`, resolving `acef2002a323d40d4.<tenant>.agents.whisper.online`, reverse-DNS'd back to that name). n8n workflows can't hold a raw socket, so this runs at the host, once, outside the workflow:

```bash
curl -fsSL https://get.whisper.online | sh          # install the CLI on the n8n host
whisper connect acef2002a323d40d4                   # local SOCKS5 → socks5h://127.0.0.1:1080
export ALL_PROXY=socks5h://127.0.0.1:1080 HTTPS_PROXY=socks5h://127.0.0.1:1080
```

Set that as n8n's process proxy, or per-node under **HTTP Request → Proxy**, and every request the workflow makes leaves from the agent's identity — the far end's access log, RDAP lookup, and reverse-DNS all point at the same agent. The **Get Egress Config** operation reads back which agent/`/128` a proxy session is bound to for display in a workflow (it strips the bearer/WireGuard key by default; the credential itself never needs to touch workflow data — `connect` runs at the host, not inside n8n). See [/docs/connect](/docs/connect) for the full egress mechanism (SOCKS5, WireGuard, AnyIP tiers).

## Verify without a key

The two keyless operations are the same public surface behind [/docs/verify](/docs/verify) and [/docs/rdap](/docs/rdap) — useful for gating a workflow on *any* address, Whisper-issued or not, with no account:

**With stock tools:**

```bash
curl -s "https://rdap.whisper.online/verify-identity?ip=2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4" | jq .
```

**With the Whisper node:** **Operation: Verify Identity**, input the address — no credential attached — returns `{is_whisper_agent: true, fqdn, operator, dane_ok: true, jws_ok: true, evidence: {...}}`, ready for an **IF** node to branch a workflow on trust.

## Compare & next steps

The [Zapier integration](/docs/integrations) covers the same two-tier control surface for teams standardized on Zapier instead of n8n; both wrap the identical `whisper.agents` verb described in full at [/docs/control-plane](/docs/control-plane). For every other automation platform, or to call the raw endpoint yourself, see [/docs/integrations](/docs/integrations).

**Next:** [Control plane](/docs/control-plane) — the full `whisper.agents` operation reference · [Connect / egress](/docs/connect) — routing real traffic through an agent's `/128`.
