Expand description
Agent identity at the MCP boundary, jekt ids and outgoing jekt / UI-automation signatures. Split out of main.rs unchanged (SPEC_LARGE_FILE_MODULE_ANALYSIS_2026_09_30.md §4.2).
Structs§
- Outgoing
Jekt 🔒Signatures - Build the id/timestamp/host-signature/LAN-signature quadruple for an
outgoing jekt (SPEC_JEKT_TRUST_LAYER_COMPLETION_2026_08_13.md §2.2,
SPEC_JEKT_LAN_TIER_SIGNING_2026_08_15.md §2.3). Reads this process’s OWN
AGENTMUX_JEKT_KEY/AGENTMUX_LAN_KEY— injected at spawn alongsideAGENTMUX_AGENT_ID, into this agent’s env only, never any other agent’s — and signs over the same (msgid, source_agent, target_agent, ts_secs, message) material both schemes share.
Statics§
- JEKT_
MSGID_ 🔒COUNTER - Process-wide counter for
generate_jekt_msgid— millis-timestamp alone isn’t guaranteed unique if two jekts are sent in the same millisecond.
Functions§
- agent_
slug 🔒 - The calling agent’s slug (its
AGENTMUX_AGENT_ID), injected by AgentMux into this MCP server’s trusted environment. MuxAPI identity/preset/memory REST endpoints stamp theiragent_idfrom this — the agent’s own model output cannot reach those endpoints (no auth key in the PTY) nor override this value, so the slug cannot be forged. See SPEC_AGENT_APP_API_MCP_BINDINGS_2026_06_28.md §5. - build_
block_ 🔒to_ agent_ map FleetBroadcast’s block_id -> agent-name resolution (REPORT_CROSS_INSTANCE_CONTROL_ROBUSTNESS_AUDIT_2026_08_22.md): a/agentmux/discoveryresponse’shost.addressableANDhost.cross_channelsections both carry ablock_id—addressableunderagent_id/block_id,cross_channel(a different channel on this same host) undername/block_id. A block_id is unique across channels on one host, so both are folded into one map, not kept separate.lan/wanentries carry noblock_idat all (they’re not local blocks) — a target for those tiers is never in this map, and the caller falls back to treating it as a literal agent name instead (see theFleetBroadcasthandler).- generate_
jekt_ 🔒msgid - A unique-enough message id for a signed jekt: no
uuiddependency needed (this crate doesn’t otherwise pull one in) — timestamp + this process’s own pid + a monotonic counter is unique enough for its one purpose (a value both this signer and the receiving srv agree to include in the signed material, so a signature can’t be replayed under a different id). - interpret_
resolve_ 🔒response - The response half of
resolve_agent_name_at_boundary, separated so the status handling is testable without a server. - resolve_
agent_ 🔒name_ at_ boundary - Identity M3 (spec §5): resolve a typed agent name at the boundary — the
only place a name is turned into a UID — before a tool stores it.
Ok(Some(uid))when exactly one identified agent matches;Ok(None)when none does, the match has no UID, or the srv predates the endpoint (the tool then sends the name and the server records the miss).Errin two cases, both of which fail the tool call: the name is ambiguous — the error lists the candidates so the model can retry by uid (§5.2) — or the resolver could not answer (a store fault, any other non-2xx, an unreadable or unexpected response), where sending the bare name would skip the ambiguity check. Seeinterpret_resolve_response. - sign_
outgoing_ 🔒jekt - sign_
ui_ 🔒automation_ auth - Build the identity proof every
/api/v1/ui/*request carries — an HMAC-SHA256 signature over this agent’s own agent_id, using this agent’s ownAGENTMUX_JEKT_KEY(the same per-agent keysign_outgoing_jektabove uses for jekt messages; reused rather than inventing a parallel credential system). Unlike jekt signing, a missing key here is a hard error, not a silent “send unsigned” — srv has no unverified fallback path for UI automation (seecrates/srv/src/server/ui_handlers.rs’s module doc comment), so a tool call with no key would just 401 anyway; failing fast with a clear “respawn to get a key” message is more useful than a confusing round trip. - signed_
jekt 🔒 - The request for a jekt to
target_agent, signed: every send path builds it here. The target is its route name first (agent_route_name: a fork’s “Loap #3” is “Loap-3”), because the signatures bind the target: every hop routes by the route name, and normalizing a signed request at a hop would break its signature. A blank target is left blank.