Whisper · Docs
Concepts

Nested identity

An agent behind another agent. A PC that is a Whisper agent runs a browser that is also a Whisper agent and egresses through it - so the browser is nested behind the PC. Whisper detects that hierarchy, at any depth, across any mix of SOCKS5 and WireGuard, and makes it a checkable, governable fact.

Agents nest in the real world. A device holds an identity; something running on it holds its own; its traffic transits the outer one. Whisper records the parent to child relationship, shows you the live tree and its full history, documents same-owner edges publicly in RDAP and WHOIS, and - the part that matters for security - binds a child by every ancestor's egress policy. Nothing here is a new port or a new key: nesting rides the same whisper.agents control verb and the same /128 identities you already have.

How an edge is detected

Two signals, reconciled. Both are opaque to the graph proxy, so neither needs a new op.

SignalWhat it isWhere it comes from
Declaredintenta parent arg on op:connect - "I run behind this identity"
Measuredattestationthe egress tap: a nested child's connection arrives from the parent's /128 (CLIENT_SRC) while the child authenticates as its own (SRC)

Measured is ground truth: it is the observed transit, and it is what governs (below). A parent you merely declare is shown, but it never gates another identity's traffic - so no one can name a /128 they do not control to borrow, or escape, its policy.

Declare an edge when you provision the child:

CALL whisper.agents({op:'connect', args:{tier:'socks5', address:'<child /128>', parent:'<parent /128>'}})

A Tier-1.5 child (SOCKS5/HTTP egress source-bound to its /128) is measured automatically the first time it egresses through the parent. A Tier-1 (WireGuard) child is kernel-routed through its parent, so the parent governs it by routing; declare it to see it in the tree.

See the tree

op:agent returns each identity's current parent, its children, and its depth, joined live with per-connection liveness - never from the zone, so a busy nest never churns the record:

CALL whisper.agents({op:'agent', args:{address:'<child /128>'}})
# columns include: parent, children, children_total, depth,
#                  owner_agents_raw, owner_agents_nested_deducted, roam
#
# parent = { "parent": "2a04:2a01:92b1:49e2:8487:9d44:64d6:cb51",
#            "parent_handle": "t6b3a5f3...",   // the parent's OPAQUE tenant handle
#            "source": "declared", "active": false, "orphaned": false }
# depth  = 1

parent_handle is an opaque t<sha256> handle, never a raw account id - so a child always sees the identity it is behind, even across owners, without deanonymizing it. owner_agents_raw counts every /128; owner_agents_nested_deducted counts only root endpoints, so a fleet's true footprint is visible both ways. A child that stops egressing goes stale and then leaves the live tree while its history is kept; re-nest it under a different parent and both the current pointer and the timeline stay correct.

Documented in RDAP and WHOIS

A same-owner edge is public by default, the same way an identity's /128 is: the child's RDAP record carries a related link to its parent plus a "Nested identity" remark, and WHOIS shows a nested-behind: line. It is synthesized from the DNSSEC-signed zone, so it is byte-identical on every node via AXFR.

curl -H 'accept: application/rdap+json' https://ns1.whisper.online/ip/<child /128>
# -> links[]: ... { "rel":"related", "title":"nested behind (transit parent identity)", "href":".../ip/<parent>" }
#    remarks[]: "Nested identity - this /128 egresses behind another Whisper identity."

A cross-owner edge is suppressed from the public surface by default (your agent transiting someone else's network is not published without consent). Either endpoint of a same-owner edge can opt out and the public link disappears while the owner still sees it:

CALL whisper.agents({op:'policy', args:{address:'<child /128>', nesting_opt_out:true}})
# -> policy rows include ['nesting_opt_out', 'true']

Opt-out is publish-before-commit: the public zone is rewritten first, so the flag can never report success while the AXFR'd record still exposes the edge.

Bound by every ancestor's policy

This is the security guarantee. A nested child's effective egress policy is its own firewall intersected with every live ancestor's - most-restrictive-wins. A DENY at any layer wins; a kill-switched or revoked ancestor cuts every descendant behind it. Because the child's final hop is Whisper-mediated (it sources from its own /128), that composition is enforced in software over the measured chain, evaluated once per connection:

So governance flows down the tree by construction: restrict the PC and the browser behind it inherits the restriction; kill the PC and the browser's egress stops with it.

Roaming (for partners)

The parent an agent egresses behind is a network. op:agent {roam:true} returns the ordered history of parent networks a device has roamed through - each as its opaque parent_handle, with first-seen, last-seen and connection counts - folded from the warm activity store:

CALL whisper.agents({op:'agent', args:{address:'<child /128>', roam:true}})
# -> roam: [ { "parent_handle":"t89a2...", "first_seen":..., "last_seen":..., "connections":42 }, ... ]

An MSSP that governs several client tenants recomputes each managed tenant's handle and matches it against these - so it can tell when a managed device has landed behind another managed client's network versus a foreign one. The handles are opaque, so a foreign network stays anonymous; only a network the partner already governs de-opaques.

What it is, and isn't

Next

See /docs/identity for the /128 an agent nests behind, /docs/connect for the SOCKS5/WireGuard tiers that produce a measured edge, and /docs/egress-governance for the per-agent firewall that composes down the chain.