# Power Platform

**A custom connector so Power Automate flows and Logic Apps can verify — and govern — real agent identities, with zero code and zero infrastructure.**

## The pain

Your Power Automate flow just received a webhook from something claiming to be an autonomous agent. Maybe it's an approval callback, maybe it's a payment trigger, maybe it's a step in a multi-agent pipeline built in Copilot Studio. The trigger carries a source IP. You have no low-code way to answer the only question that matters — *is this a real, currently-provisioned agent, or a spoofed request from anywhere on the internet?* — without dropping into an Azure Function, wiring up raw HTTP actions with hand-built headers, and parsing whatever comes back. Multiply that by every flow that touches agent traffic, and you've built the same bespoke verification action a dozen times, none of them consistent, none of them getting the DNSSEC/DANE chain right, and none of them able to actually *provision or shut down* the agent when you find a problem.

Whisper closes that gap with one thing: a proper Power Platform **custom connector** — an Independent Publisher connector, `Whisper Agent Identity` — that gives every flow a native action for identity verification, and, if you supply an API key, native actions to register, list, police, and revoke agents. No Azure Function, no raw HTTP action, no hand-rolled header. Drag the action into the canvas, fill in two fields, done.

## The standard underneath: what "verifying an agent" actually checks

Whisper agent addresses are real, routable IPv6 `/128`s allocated out of `2a04:2a01::/32` (announced by `AS219419`). "Is this address a real Whisper agent" is not a lookup in a proprietary table — it's a chain of open, independently-checkable steps, all run server-side for you by the keyless verification endpoint:

1. **Reverse DNS (PTR)** — the address reverse-resolves to a canonical name like `acef2002a323d40d4.<tenant>.agents.whisper.online` (reverse DNS per RFC 1035, with IPv6 `ip6.arpa` delegation per RFC 3596).
2. **Forward-confirming reverse DNS (FCrDNS)** — resolving that PTR name's `AAAA` record must round-trip back to the original address, so a PTR alone (which anyone can point anywhere) proves nothing without this forward check.
3. **DANE-TLSA pin (RFC 6698)** — a `TLSA` record under the agent's name pins its TLS certificate (`3 1 1` = DANE-EE, SHA-256 of the SPKI), so the name can't be MITM'd even if a CA is compromised.
4. **Signed identity document** — an ES256-signed JWS binding the address, the hostname and the issuing tenant, checkable against Whisper's published fleet key.

The keyless endpoint runs all four steps and returns one verdict — `is_whisper_agent`, `dane_ok`, `jws_ok`, plus the supporting evidence — so a flow author never has to orchestrate the chain by hand. Full mechanism: [`/docs/verifiable-identity`](/docs/verifiable-identity) and [`/docs/dane`](/docs/dane).

## The raw HTTP calls the connector wraps

Every keyless operation is one plain HTTPS request — you could reproduce all of this in a flow with raw **HTTP** actions and manual JSON parsing, which is exactly the boilerplate the connector removes.

```bash
# Verify identity end-to-end (PTR + FCrDNS + DANE + signed doc)
GET https://rdap.whisper.online/verify-identity?ip=2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# { "is_whisper_agent": true, "fqdn": "acef2002a323d40d4.<tenant>.agents.whisper.online",
#   "dane_ok": true, "jws_ok": true, ... }

# The RDAP record (RFC 9083)
GET https://rdap.whisper.online/ip/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4

# Register / list / revoke (the control plane) — one Cypher verb over HTTPS
POST https://graph.whisper.security/api/query      # header: X-API-Key: whisper_live_xxx
{ "query": "CALL whisper.agents({op:'register', args:{label:'invoice-bot'}})" }
```

The full terminal walk (with `dig`/`openssl`) is on [Verify an agent](/docs/verify) — but in Power Automate you never leave the flow.

## With Whisper: the custom connector

The connector ships as an **Independent Publisher** connector — `Whisper Agent Identity` — importable straight from the swagger definition, or (once merged) discoverable in the Power Platform connector gallery like any first-party connector. The connector package is a swagger/OpenAPI definition plus its connection properties, importable straight into Power Platform; the Independent Publisher submission is pending review.

### One connection, two tiers

There is exactly **one** connection parameter: **Whisper API key** (`securestring`, optional). Per Postel's Law — be liberal in what you accept — the connector works with it blank:

| | No key | With key |
|---|---|---|
| Verify agent identity | ✅ | ✅ |
| RDAP lookup | ✅ | ✅ |
| Transparency log | ✅ | ✅ |
| Inbound lookups | ✅ | ✅ |
| Register / List / Set policy / Logs / Revoke | 400, clear error | ✅ |

Under the hood the key is attached only to the five control operations, via a header policy that fires exclusively on those operation IDs — the four keyless actions never see it and never need it. An anonymous call to a control action doesn't 500; it comes back as a clean, structured error: *"anonymous callers cannot use the agent control plane — an attributable API key is required."* That's the Robustness Principle showing up as a design decision, not a slogan: the connector is strict about what it emits (a typed, documented, RFC-conformant reply) and permissive about what it accepts (key or no key, same connector, same actions visible).

### The nine actions

**Keyless**, served from `rdap.whisper.online`:

| Action | What it returns |
|---|---|
| **Verify agent identity** | One verdict: `is_whisper_agent`, `fqdn`, `dane_ok`, `jws_ok`, evidence. |
| **RDAP lookup for an agent address** | Full RFC 9083 IP-network object. |
| **Get identity transparency log** | Hash-chained, ES256-signed issuance/revocation events. |
| **Get inbound identity lookups** | k-anonymised feed of who has resolved/queried this agent's name. |

**Control**, served from the Whisper control plane (`graph.whisper.security`), require the key:

| Action | What it does |
|---|---|
| **Register a new agent** | Mints a fresh `/128` + agent API key (`op:register`), returned once. |
| **List your agents** | Your fleet, scoped to your tenant (`op:list`). |
| **Set resolver policy** | Per-tenant DNS allow/deny + list policy (`op:policy`). |
| **Get activity logs** | Recent DNS / connection / allocation activity (`op:logs`). |
| **Revoke an agent** | Irreversibly withdraws the `/128`, PTR, tokens, key (`op:revoke`). |

Each control action carries a **`query`** field pre-filled with the exact `whisper.agents` Cypher `CALL` for that operation — you edit the values inside `args` (the label, the policy lists, the agent id) directly in the flow designer; the connector POSTs `{"query": ...}` to the control plane verbatim. This is a deliberate design choice: rather than reinvent a bespoke schema per action, the connector exposes the same control verb documented in [`/docs/control-plane`](/docs/control-plane), so what you learn in Power Automate transfers directly to the CLI and every other SDK.

### A flow: verify on trigger, revoke on failure

A minimal but real flow — an HTTP-trigger flow that gates on agent identity before doing anything else:

1. **Trigger** — *When an HTTP request is received*, body includes `source_ip`.
2. **Action** — `Whisper Agent Identity` → **Verify agent identity**, `ip = triggerBody()?['source_ip']`.
3. **Condition** — `is_whisper_agent == true` **and** `dane_ok == true`.
   - **Yes** → continue the business flow (e.g. approve the payment).
   - **No** → `Whisper Agent Identity` → **Revoke an agent** (if you provisioned it) or route to a Teams/email alert with the `detail` field from the verdict.

Swap step 2 for **RDAP lookup** if you only need the registrant/country/status fields, or add **Get inbound identity lookups** as a scheduled flow to build a lightweight per-agent access dashboard entirely inside Power BI, fed by a Power Automate recurrence trigger — no separate ETL job.

## Installing it

Until the connector lands in the shared gallery, import it as a **custom connector** from the swagger definition:

1. Power Automate → **Data → Custom connectors → New custom connector → Import an OpenAPI file**.
2. Upload the connector's `apiDefinition.swagger.json` (host `rdap.whisper.online`, five control operations dynamically re-hosted to `graph.whisper.security`).
3. Create a connection; paste your `whisper_live_...` key if you want the control actions, or leave it blank for keyless-only.
4. Test each action from the connector's **Test** tab before wiring it into a flow.

> No connector icon ships with an Independent Publisher submission — Power Platform convention. The connector's brand colour (`#7a40ff`) is set instead so it's recognisable in the action picker.

## Related integrations

If your automation platform is Dify rather than Power Platform, the same two-tier keyless/keyed model ships as a Dify plugin — see [`/docs/integrations`](/docs/integrations) for the full no-code matrix (n8n, Zapier, Make, Pipedream, Dify, Power Platform). All of them call the identical public endpoints and the identical `whisper.agents` control verb described here — there is one control plane, not six.

---

**Next:** [Verifiable identity](/docs/verifiable-identity) for the full verification-chain mechanism, or [Control plane](/docs/control-plane) for every `whisper.agents` operation the control actions map to.
