feat: agentmask + service discovery infrastructure#952
Conversation
Add the @ocap/agentmask package with an OpenClaw plugin that lets an LLM agent request and use wallet capabilities from a MetaMask capability vendor via the OCAP kernel daemon. The plugin provides three tools: - metamask_request_capability: redeem OCAP URL and request capabilities - metamask_call_capability: call methods on obtained capabilities - metamask_list_capabilities: list capabilities obtained in the session Also includes docs migrated from the extension repo (capability-vendor, demo-two-way-comms, kernel-guide) and updates demo-two-way-comms with parallel Manual CLI / OpenClaw agent instructions for the away side. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…edemption The agent can now ask the user for their OCAP URL during conversation and redeem it on the fly via the new metamask_obtain_vendor tool, rather than requiring the URL to be pre-configured in .env or plugin config. - Add metamask_obtain_vendor tool (accepts URL, redeems, stores vendor kref) - Move ocapUrl into mutable PluginState (seeded from config, overridable) - ensureVendor() directs the agent to metamask_obtain_vendor when no URL set - Update SKILL.md workflow and demo doc OpenClaw section Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion__ After obtaining a capability from the vendor, request_capability now calls __getDescription__ on it to retrieve method schemas (name, args, return type). The full schema is shown in the tool response and stored in plugin state. list_capabilities also shows method names. Discovery is best-effort — if the capability is not discoverable, the tool still works without method listings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning MetaMask internal reviewing guidelines:
|
Pre-redemption of the configured matcher URL was fire-and-forget, so a tool call landing during the redemption window would see a misleading 'no matcher connection' error from requireMatcher. Park the pending promise in state.matcherPending and have requireMatcher await it, surfacing the underlying failure when redemption rejects.
… discovery/daemon.ts Both OpenClaw plugins kept a near-identical copy of the daemon caller; the discovery version added optional ocapHome support, so a future fix in one copy would drift from the other. Sync the two files (metamask now accepts the same optional ocapHome param, even though it does not use it today) and add a header note instructing future editors to keep them in sync. Plugins remain self-contained so 'openclaw plugins install -l' still works on either directory in isolation.
- ocap-kernel(OcapURLManager): propagate OcapURL{Issuer,Redemption}Service
through getServices / getIssuerService / getRedemptionService
- service-discovery-types(matcher): add _AssertSameShape drift guards
for ServiceQuery and ServiceMatch
- service-discovery-types(contact): tag ContactResponse with a 'kind'
discriminator so a ServicePoint whose API happened to define
credentialSpec / requiredCertifications can't be misclassified;
update sample-services and the discovery plugin to match
- kernel-utils(libp2p-relay): type tersePeer / terseAddr with PeerId
and Multiaddr instead of any
- kernel-node-runtime(rpc-socket-server): narrow unlink catch to
ENOENT so EPERM/EBUSY/EISDIR surface instead of becoming opaque
EADDRINUSE from the subsequent listen()
- llm-bridge(conversation): commit user turn to persistent history
only after the assistant reply lands; a failed client.chat would
otherwise leave an unpaired user turn and corrupt the next ingest
- service-matcher(matcher-vat): distinguish 'all bridge-cited ids
unknown' from 'no matches' — the former throws so a hallucinating
ranker is loud, not silent
- discovery plugin(state): collapse matcher + matcherPending into a
discriminated MatcherSlot ('absent' | 'pending' | 'resolved') so
the type system rules out the contradictory both-set state
- discovery + metamask plugins: replace hand-rolled safeParse with a
superstruct wrapper per CLAUDE.md conventions, eliminating the
per-field typeof ladder and the KNOWN_KEYS drift hazard
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 91440a1. Configure here.
@libp2p/interface declares Multiaddr but does not re-export it, so the build failed under the stricter library check in CI. Import it from its authoritative module and declare the dependency explicitly.
CapData bodies are smallcaps-encoded JSON with a leading '#' marker, so the previous JSON.parse(body) always threw and the catch returned undefined — making 'kind !== public' true for every response and rejecting every public contact as non-public. Match the kind field by regex against the raw body, the same way extractKref reaches into it.

Summary
rekm/agentmaskbranch as base (agentmask vats, OpenClaw MetaMask vendor plugin, capability schema discovery) ontomainImportant caveat: this requires using the updated version of the MetaMask browser extension (Erik's updates to put the ocap kernel into it and then some further stuff I needed to add on top of that) in the
chip/agentmaskbranch of themetamask-extensionrepo. While the changes this PR represents are being proposed for merging into ourmainbranch, we don't really have that option for the browser extension since it's not our repo to mess with. (I suppose we could merge it with some negotiation with the MetaMake team, but since it's highly experimental I'm pretty sure they wouldn't be too keen on that idea. I believe Erik's plan was to eventually have it in under a flag, but I don't thing that's yet an option.)Test plan
packages/agentmask/openclaw-plugin-discovery/VALIDATION.mdend-to-end (matcher daemon and LLM service consumer on VPS, sample services + MetaMask browser extension (providing MetaMask services) on laptop, OpenClaw agent driving discovery and contact)Note
Medium Risk
Large new surface (LLM-driven wallet/signing and service contact) plus daemon/relay operational changes; correctness depends on experimental MetaMask extension integration documented outside this PR.
Overview
Introduces
@ocap/agentmaskas a monorepo home for AgentMask / OpenClaw integration: long-form docs (capability vendor, two-way kernel comms, host-developer kernel guide), plus two installable plugins that drive theocapdaemon viaredeem-urlandqueueMessage.@openclaw/metamaskexposes tools to redeem a vendor OCAP URL,requestCapability, call capability methods, and list session capabilities (with Vitest coverage).@openclaw/discoveryadds matcher-centric tools (discovery_find_services, contact initiation,service_call, tracked state) and a SKILL that forces matcher-first workflows instead of hard-coded services.@metamask/kernel-cligains a global--homeflag (per-invocationOCAP_HOME), relay--public-ip/ separate~/.libp2p-relaybookkeeping, and stricter daemon startup (PID interlock, no silent socket takeover)..yarnrc.ymlforwardsHTTPS_PROXYfor sandboxed installs;.claude/settings.jsonrelaxes sandbox network/filesystem for Yarn.End-to-end validation is documented in
VALIDATION.md(matcher + consumer on VPS, MetaMask extension + sample services on laptop); the matching MetaMask extension changes live on a separate branch, not in this repo.Reviewed by Cursor Bugbot for commit 9f0e86d. Bugbot is set up for automated code reviews on this repo. Configure here.