picolabs.atlassian.net

Audience: KRL developers and engine operators
Engine version: 1.6+
Parent: Identity System

What this page covers

Every pico in pico-engine 1.6+ has a cryptographic identity expressed as a DID (Decentralized Identifier). This page explains what those DIDs arehow to find them, and how to use them in KRL.

It does not cover subscription formation, lifecycle, or routing — that belongs on Subscriptions.

Why DIDs?

Picos need a stable answer to “which pico is this?” that survives beyond a single channel ECI or engine instance. DIDs provide that for pico-to-pico work: introductions, encrypted traffic, and (eventually) verifiable credentials.

DIDs are a separate plane from the other identity mechanisms:

Mechanism

Identifies

You use it when…

Mechanism

Identifies

You use it when…

Passkey

A human at the browser

Using the developer UI or session-gated /c/* APIs

DID

A pico as an actor

Picos talk to each other (queries, events, intros)

OAuth Bearer

An external integrator

Webhooks, Home Assistant, third-party apps on /sky/*

Humans sign in with a passkey; your root pico is your agent and holds a DID. Picos use DIDs outward; external apps use OAuth.

Two DIDs, two jobs

Pico-engine uses two DID methods. They are complementary, not redundant.

DID

Role

Cardinality

Think of it as…

DID

Role

Cardinality

Think of it as…

did:webvh

Portable pico identity — who the actor is

One per pico

The pico’s passport

did:peer

Private relationship identity for one subscription pair

One per established subscription

A phone number for that relationship only

did:webvh is provisioned automatically when a pico is created. Share it when someone needs to introduce themselves to your pico (for example as target_did when forming a subscription).

did:peer is minted during the SKY intro handshake when a subscription is approved. Use it for ongoing query and event traffic on that subscription. Do not share a peer DID to start a new subscription — always use the recipient’s did:webvh at create time.

ECIs (channel ids) are still the local policy gate on each engine. DIDs identify picos and relationships; ECIs enforce what a caller may do on this engine.

did:webvh — portable pico identity

Provisioning

Every pico receives a did:webvh at creation — root picos, child picos, and picos created before 1.6 (provisioned on first load after upgrade).

The DID document log is served at:

GET /picos/{picoId}/did.jsonl

The engine embeds PICO_ENGINE_BASE_URL in the document. For cross-engine use, that URL must be stable and peer-reachable (not just what you type in a local browser tab).

Finding a pico’s did:webvh

Where

How

Where

How

Developer UI

Open the pico → Subscriptions tab → Identity panel → did:webvh (myDid)

KRL

wrangler:myDid()

HTTP

Fetch {base}/picos/{picoId}/did.jsonl

Give partners your did:webvh when they need to subscribe to you or resolve who you are. Do not give them a did:peer for that purpose.

did:peer — subscription relationship identity

After two picos complete a DID-based subscription intro, each side stores the remote party’s did:peer on the established subscription (Tx_didRx_did).

Peer DIDs are private to that relationship. They are used for encrypted SKY traffic (DIDComm) when picos are on different meshes or engines, and for routing queries and events once the subscription exists.

→ How peer DIDs are created and used: Subscriptions

Public intro

Public intro controls whether a pico accepts unsolicited SKY intro messages addressed to its did:webvh.

Pico

Default

Pico

Default

Root pico

On (publicIntro: true)

Child pico

Off

Any pico may enable public intro — for example a community or registry pico that should accept subscriptions from strangers.

Where

How

Where

How

Developer UI

Subscriptions tab → Identity → Public intro checkbox

KRL query

wrangler:publicIntro()

KRL event

wrangler:set_public_intro with attribute enabled: true or false

Cross-engine subscriptions usually require the recipient to have public intro enabled (or an existing relationship path).

Using DIDs in KRL

Query a remote pico by DID

wrangler:picoQuery(<did_webvh_or_peer>, "io.picolabs.wrangler", "id", {})

The engine routes over an established subscription when one exists for that DID. Otherwise it may resolve a did:webvh directly (cold query) if the peer is reachable.

picoQuery accepts did:webvh or did:peer. It does not accept an ECI — use picoQuery with an ECI for classic (non-DID) remote calls.

Send an event by DID

event:send({ "did": "<did_webvh_or_peer>", "domain": "wrangler", "type": "ping", "attrs": {} })

For traffic on an established subscription, you can also pass the full subscription map:

event:send({ "sub": subscription, "domain": "wrangler", "type": "ping", "attrs": {} })

See the event library docs in the developer UI for details. Subscription formation and the layer2: true attribute are documented on Subscriptions.

Know who sent a cross-pico event

When the engine delivers an inbound cross-pico event, rules may read the sender’s portable identity:

wrangler:callerDid()

Returns the sender’s did:webvh when the engine provides it; otherwise null.

Wrangler identity API

Query / action

Returns / effect

Query / action

Returns / effect

wrangler:myDid()

This pico’s did:webvh

wrangler:publicIntro()

Whether unsolicited SKY intro is accepted

wrangler:set_public_intro event (enabled)

Toggle public intro

wrangler:callerDid()

Sender’s did:webvh on inbound cross-pico events

wrangler:picoQuery(did, …)

Query a remote pico by did:webvh or did:peer

Identity primitives are implemented in the engine dido module and exposed through wrangler queries and events.

DIDs are not…

Not passkeys. Passkeys authenticate you to your mesh. DIDs identify picos to each other.

Not OAuth. OAuth authorizes external HTTP callers on /sky/*. Pico-to-pico traffic uses SKY and DIDComm (or verified local dispatch on the same engine), not Bearer tokens.

Not ECIs. An ECI is a channel address and policy gate on one engine. A DID is a portable cryptographic identity. Established subscriptions still have an Rx ECI where policy is enforced locally.

Not a replacement for family channels. Parent and child picos communicate through family channels, not subscriptions or DIDs.

Configuration

Variable

Relevance to DIDs

Variable

Relevance to DIDs

PICO_ENGINE_BASE_URL

Embedded in every did:webvh; must be stable and peer-reachable for portable identity and cross-engine resolution. Defaults to http://localhost:$PORT.

See the Environment variables page for the full list (passkey and OAuth variables are on the sibling identity pages).

Related pages

Deprecated: io.picolabs.did-o ruleset — use wrangler:picoQuery and event:send with DIDs instead.

Read the original on picolabs.atlassian.net ↗