Dify
Your Dify agent can already browse the web and call APIs — it just can't prove to anyone, including you, which agent did it, or stop a compromised one from doing it again.
Dify apps run behind a shared NAT egress IP indistinguishable from every other tenant, so "which of my 40 agents hit this API" is a grep through logs you have to trust, and "kill that agent's network access" means editing the app instead of revoking an identity. The Whisper Agent Identity plugin fixes this at the network layer: a Dify tool-call gets real, routable IPv6 identity — verify any address, provision a new one with its own /128, govern it, and (Dify being self-hostable) route the agent's traffic through that address.
It ships as a standard Dify tool plugin, installable straight from GitHub today, with a Marketplace listing in review. Like every Whisper integration it is two-tier: the verification tools work with zero configuration and no account, and pasting in a Whisper API key unlocks the control plane.
Install it
GitHub install (live now). In Dify: Plugins → Install Plugin → Install from GitHub, point at whisper-sec/dify-plugin, pick the latest release. No build step.
Marketplace (pending review). langgenius/dify-plugins#2636 ships the packaged .difypkg for one-click install from Dify's in-app marketplace once merged.
Build it yourself — the source is plain Python + YAML, no Whisper tooling required:
# stock tools only
gh release download -R langgenius/dify-plugin-daemon \
--pattern 'dify-plugin-linux-arm64' -O /tmp/dify-plugin && chmod +x /tmp/dify-plugin
git clone https://github.com/whisper-sec/dify-plugin whisper-dify
/tmp/dify-plugin plugin package ./whisper-dify -o whisper-agent-identity-0.1.0.difypkg
Open the plugin's Authorize panel and you'll see exactly two optional credentials: api_key (a whisper_live_… key) and egress_proxy (a local proxy URL). Both blank is a fully working install.
The nine tools
The plugin is one Dify tool provider (provider/whisper.yaml) exposing nine tools, split cleanly along the auth boundary:
| Tier | Tool | Wire call |
|---|---|---|
| Keyless | Verify Agent Identity | GET /verify-identity?ip=<addr> |
| Keyless | Lookup RDAP Record | GET /ip/<addr> |
| Keyless | Get Transparency Log | GET /ip/<addr>/transparency |
| Keyless | Get Inbound Lookups | GET /ip/<addr>/lookups |
| Control (needs key) | Register Agent | CALL whisper.agents({op:'register'}) |
| Control (needs key) | Set Policy | op:'policy' |
| Control (needs key) | Get Logs | op:'logs' |
| Control (needs key) | Revoke Agent | op:'revoke' |
| Control (needs key) | Get Egress Config | op:'connect' |
The keyless tools hit the public gateway rdap.whisper.online over plain HTTPS — no header, no cookie. The control tools all funnel through the one Whisper control verb, CALL whisper.agents({op, args}), POSTed as Cypher to https://graph.whisper.security/api/query with the caller's key in X-API-Key. The plugin never invents a second API surface; it's a thin, typed wrapper over the same verb the CLI uses, so a tool's behavior is exactly what whisper on your terminal would do. The DoH resolver (/dns-query) is deliberately not exposed as a tool — a DNS-message-in/DNS-message-out endpoint is a broken building block for an LLM tool call.
Verify an agent
Verify Agent Identity answers "is this address a genuine Whisper agent, and who runs it?" by checking that the forward name for the agent's /128 and the reverse PTR agree — the same forward-confirmed reverse DNS trick operators have used since split-horizon anti-spoofing became common practice, formalized here as one call.
Independently, from a terminal, that's a forward-confirmed-reverse-DNS check plus an RDAP lookup — the full walk is in Verify an agent. In Dify it's one tool call:
Verify Agent Identity address = 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
{ "is_whisper_agent": true,
"fqdn": "acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online",
"dane_ok": true,
"jws_ok": true,
"evidence": {
"ptr": "4.d.0.4.d.3.2.3.a.2.0.0.2.f.e.c.4.7.a.c.a.5.b.e.1.0.a.2.4.0.a.2.ip6.arpa",
"forward_aaaa": "2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4",
"agent": "acef2002a323d40d4" } }
The PTR resolves back to the exact address it claims (forward_aaaa), and the leaf is pinned by a DNSSEC-anchored TLSA record (dane_ok) whose transparency entry is signed (jws_ok) — three independent confirmations in one call. An address that anchors no agent — or where forward and reverse disagree — returns is_whisper_agent: false with the specific reason, never a bare 404. That's the same liberal-input contract as whisper verify and every keyless SDK call: never an opaque error, always a verdict plus evidence.
Get Transparency Log is the deeper check: it returns the hash-chained, signed record of every issuance event for that /128 — the append-only ledger analogue of Certificate Transparency (RFC 9162)'s core idea applied to address identity rather than X.509 leaves, so a party who doesn't trust Whisper's word can still verify the chain itself rather than trust a point-in-time API answer.
Register & govern
With stock tools, provisioning a routable, verifiable per-agent identity is not something curl/openssl do for you — there's no RFC for "mint me an IPv6 /128 with reverse DNS, a TLSA record, and a revocation path" you can hand-roll from a resolver. This is exactly the gap the control plane fills.
With the Dify tool:
Register Agent name = scout contact_email = ops@example.com
{ "agent": "scout",
"address": "2a04:2a01:…",
"fqdn": "a<interface-id>.<your-tenant>.agents.whisper.online",
"api_key": "whisper_live_…",
"state": "active" }
The /128 is freshly minted from AS219419 space under your tenant (not the demo's), so the reverse name lands in your own …agents.whisper.online label — exactly the identity you just learned to verify.
The key is returned exactly once — register_agent.py surfaces it in the tool's text summary ("api_key returned once — store it now") precisely so it doesn't silently vanish into workflow logs. From there, Set Policy writes the tenant's DNS allow/deny bundle, Get Logs reads back recent DNS/connection/allocation activity for auditing inside a Dify workflow, and Revoke Agent tears the identity down — withdrawing the /128, its PTR, its tokens, and its key in one irreversible call, so a compromised or retired agent can be cut off from a chat message instead of a config edit.
Egress: making it real, not just observed
Verification and governance are half the story; the other half is that Dify is self-hostable, so an agent's actual traffic can leave from its /128 instead of the shared platform IP. Get Egress Config reports the binding but — by design — never returns the raw egress bearer or WireGuard key, so nothing secret leaks into workflow data. Bring up real egress with the open-source CLI on the Dify host, then point the deployment (or just this plugin's egress_proxy credential) at it:
curl https://get.whisper.online | sh
whisper connect --port 1080
# → socks5h://127.0.0.1:1080, bound to your /128
# egress.compose.yaml — applied to plugin_daemon, api, worker
environment:
ALL_PROXY: socks5h://host.docker.internal:1080
NO_PROXY: localhost,127.0.0.1,db,redis,weaviate,sandbox,plugin_daemon,api,ssrf_proxy
docker compose -f docker-compose.yaml -f egress.compose.yaml up -d
curl --proxy socks5h://127.0.0.1:1080 https://api64.ipify.org
# → your agent's own /128; confirm the identity at /docs/verify
Full recipe, including the whole-deployment vs. single-plugin tradeoff, is in the plugin's shipped EGRESS.md.
Source
Plugin source: github.com/whisper-sec/dify-plugin (MIT). Control-verb reference client: github.com/whisper-sec/whisper-cli.
Next: Integrations overview · MCP server