# 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**, 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. The node has two resources: **Agent Control**, the ten operations below, and **Graph**, which queries the whisper.security graph itself (raw Cypher plus 29 named catalog recipes - see [Beyond agent control](#beyond-agent-control-the-graph-resource)).

## 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.online/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 `{code, message, retryable}` object on that same `error` key (`FORBIDDEN_SCOPE`, `BAD_ARGS`, and so on), 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.online/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.

## Beyond agent control: the Graph resource

Provisioning is one half of the node. Switch the **Resource** dropdown from **Agent Control** to **Graph** and the same node queries the whisper.security graph itself - the cognition layer behind [/docs/graph-api](/docs/graph-api) - without a Function node or a hand-written Cypher string. **Run Cypher** takes any query plus a `$parameters` map and posts it as-is; below it sit **29 named catalog recipes** generated straight from the graph's own catalog, so the dropdown never drifts from what the graph actually offers: 14 direct procedures (`whisper.assess`, `whisper.identify`, `whisper.variants`, `whisper.walk`, `whisper.origins`, `whisper.history` and its WHOIS projection, `whisper.psl.tldPlusOne` / `.affiliation`, `whisper.asSet`, `whisper.explain`, `whisper.lookupTorRelay`, `whisper.submit`, and `db.schema`) and 15 multi-step flows (typosquat and brand-impersonation scanning, subdomain-takeover detection, BGP-hijack exposure, supply-chain concentration, attack-surface mapping, and the rest of the console's workflow gallery), each one running by slug through the same SSE run endpoint the console uses. Every recipe carries its own `docsUrl` back to the graph-procedure reference, so a node dropped mid-workflow is also a link to the underlying documentation.

Where **Agent Control** needs your key for every write and none of its reads, **Graph** is a single credential-gated resource: every recipe here runs against the graph, which is a keyed surface, so unlike Verify Identity or RDAP Lookup on the Agent Control side, the Graph resource always expects the **Whisper API** credential attached.

## 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 list --kind agents --json | jq -r '.rows[0].result.rows[][1].agent'); do
  whisper logs --agent "$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 --agent 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`.
