@agenticprimitives/agent-resolution

中文文档
0.0.0-alpha.21发布于 2026/10/26MITTypeScriptES Module零依赖近 30 天下载 3366

Provider-neutral agent resolution primitives: agent discovery policy, signed sequenced AgentServicePublication with anti-rollback verification, private resolution grants, connection invitations, audience projection, and resolution provider ports. Resoluti

原始使用文档
文档目录13 节
  1. The rule
  2. Four independent dimensions
  3. Worked flow — Agent A reaches a nameless treasury (Agent B)
  4. Diagrams
  5. Local apps — term → Worker map
  6. Worked sequence — DNTLS as a Ring-1 resolution provider
  7. A hash proves unmodified . It does not prove current .
  8. Rotation is cheap; identity never moves
  9. Private resolution grants, not private names
  10. Bootstrap, resolver, storage
  11. Scope
  12. Install
  13. License

@agenticprimitives/agent-resolution

Part of Agentic Primitives — the open-source trust substrate for agentic applications: identity that can sign, authority checked at act time, evidence the owner carries. Developer kit · All packages

Every agent has a canonical identity. Naming is optional. Public listing is optional. Inbound addressability is optional. Authorized private resolution is a first-class capability.

Provider-neutral primitives for answering "may this party discover how to reach this agent, and where is it right now?" — with a hard wall between that question and "may this party use it?"

Spec: [specs/338](https://github.com/agentictrustlabs/agenticprimitives/blob/master/specs/338-private-agent-resolution-and-service-publication.md) · Doctrine: ADR-0056


The rule

A resolution grant answers:      "May this party DISCOVER how to reach this agent?"
It NEVER answers:                "May this party USE this agent?"

Successful resolution gives you an endpoint and a verified peer identity. Invocation still requires the whole chain, re-run at the origin:

delegation ∩ entitlement ∩ tool/action policy ∩ exact invocation proof ∩ revocation ∩ audit

Resolution is one of four orthogonal concerns with custody ("who signed"), admission ("may these bytes enter"), and authority ("what may this principal do"). A yes to one is never a yes to another.

Four independent dimensions

"Nameless" = no public label only. Listing, resolution, and inbound are modelled separately.

Posturenaminglistingresolutioninbound
Public commercial agentpublicpublicpublicdelegation-required
Public name, protected detailspublicpublicauthenticateddelegation-required
Private partner agentprivate-labelnoneinvitationknown-peer
Pairwise treasury agentprivate-labelnonepairwisedelegation-required
Unnamed internal workernonenoneinvitationknown-peer
Temporary direct agentnonenonedirectdelegation-required
Background outbound workernonenonenoneoutbound-only
import { discoveryPolicyFromPreset, validateDiscoveryPolicy } from '@agenticprimitives/agent-resolution';

const policy = discoveryPolicyFromPreset('private-partner');
validateDiscoveryPolicy(policy); // [] — combinations that cannot be enforced are rejected

Every path resolves to the same canonical identity: eip155:<chainId>:<SmartAgentAddress>.

Worked flow — Agent A reaches a nameless treasury (Agent B)

Scenario: Agent A (caller SA for a person/org) must call Agent B (treasury service SA) over A2A. B has no public ANS name (naming: none, listing: none). Reachability is invitation / private-grant resolution — not a public label.

Where the A2A URL comes from: it is not invented by the private resolver and not looked up by name. It is a field on a signed AgentServicePublicationV1:

publication.surfaces[] → entry with protocol: 'a2a' → uri (e.g. https://xyz.example/a2a/v1).

The resolver only admits Alice’s grant and selects a pre-signed publication from B’s owner vault (selectPresignedPublication — select, never edit). Alice extracts the URI after verifyPublication on her side.

Diagrams

1. Conceptual flow — nameless Agent A → treasury Agent B (terms used everywhere below):

Nameless private resolution flow — Agent A to treasury Agent B

Agent A → nameless treasury B. Vault holds signed publication (A2A uri in surfaces[]), subject-bound grant, publication authority. Steps: issue grant → invitation (initialPublication + rendezvous) → first dial or resolver refresh (selectPresignedPublication) → A2A + delegation. Resolver never forges the endpoint.

2. Local architecture — same terms → monorepo Workers:

Local architecture — apps mapped to nameless resolution terms

demo-web-pro / demo-sso-next = Agent A; demo-resolver :8795 = private resolver; demo-publications :8796 = pub store; demo-a2a :8787 = B’s A2A host (URI in publication). Optional demo-edge. Steps match diagram 1. Live treasury may still use a known URL + delegation; private resolve is the parallel Ring-1 path.

StepWhat movesA2A endpoint?
1B issues PrivateResolutionGrantV1 (subject-bound to A)no — grant = may discover
2Invitation to A = initialPublication + grant + rendezvousyes — URI already inside initialPublication.surfaces[]
3aFirst connect: A verifies that publication locallyURI from verified publication (no resolver hop)
3bRefresh: A → resolver → selectPresignedPublication → A verifiesyes — URI from the selected publication’s surfaces[], not from resolver logic
4A2A task + delegation ∩ entitlement ∩ policyuse, not resolve

Nameless = no public label. Publication authority = endpoint/session-key rotation is an ops publish, not a custody ceremony. Delegation = what lets A invoke treasury skills after the URL is known.

sequenceDiagram
  autonumber
  participant B as Agent B treasury SA
  participant Vault as B owner vault
  participant R as Private resolver
  participant A as Agent A
  participant A2A as B A2A host<br/>xyz…/a2a/v1

  B->>Vault: Store signed AgentServicePublicationV1<br/>surfaces: [{protocol:a2a, uri}]
  B->>Vault: Issue PrivateResolutionGrantV1 subject=A
  B-->>A: Invitation = initialPublication + grant + rendezvous

  Note over A: Resolve — endpoint is in the publication
  A->>A: verifyPublication(initialPublication)
  A->>A: a2aUrl = surfaces.find(p=>p.protocol==='a2a').uri

  opt Endpoint moved — same grant
    A->>R: Present grant + PoP
    R->>Vault: Admit + selectPresignedPublication
    R-->>A: Pre-signed publication (includes new uri)
    A->>A: verifyPublication → read surfaces[].uri again
  end

  A->>A2A: Open channel to a2aUrl
  A->>A2A: Task + delegation (other packages)
  alt Authority OK
    A2A-->>A: Result
  else Resolution grant only
    A2A-->>A: Denied — resolution ≠ use
  end

Local apps — term → Worker map

Conceptual termLocal app
Agent A appdemo-web-pro; invite inspect demo-sso-next /visibility
Agent B A2A hostdemo-a2a :8787 — /api/a2a, A2aTaskDO
Private resolverdemo-resolver :8795 — /v1/private/{challenge,resolve}
B vault (demo stand-in)demo-publications :8796 — /v1/publications
A2A uriInside publication surfaces[] → e.g. http://127.0.0.1:8787/api/a2a
Optional edgedemo-edge — /api/a2a/<handle>
Use (not resolve)Delegation gates in demo-a2a

Worked sequence — DNTLS as a Ring-1 resolution provider

DNTLS is not a dependency. A Ring-1 AgentResolutionProvider (method: 'dntls') maps a Service Record → AgentServicePublicationV1; createComposedResolver verifies SA binding (spec 338 §18). Namespace membership may be a policy predicate, never the grant. Bidirectional binding required. DNTLS alone never grants identity, delegation, MCP/A2A permission, entitlement, or custody.

sequenceDiagram
  autonumber
  participant D as DNTLS resolver<br/>(external)
  participant Adapt as dntls provider<br/>(Ring-1)
  participant AP as createComposedResolver
  actor A as Agent A
  participant A2A as B A2A host

  A->>AP: resolve({ kind:'external', method:'dntls', identifier })
  AP->>Adapt: resolve(reference, context)
  Adapt->>D: Resolve name / commitment
  D-->>Adapt: Service Record + proof
  Adapt->>Adapt: Map → AgentServicePublicationV1
  Adapt-->>AP: UnverifiedResolutionBundleV1
  AP->>AP: verifyPublication + SA↔DNTLS binding<br/>+ authorityCheck + continuity
  alt Fail
    AP-->>A: resolution failure
  else OK
    AP-->>A: VerifiedAgentResolutionV1<br/>(reachability only)
  end
  A->>A2A: Open surface URI + AP delegation
  A2A->>A2A: delegation ∩ entitlement ∩ policy
  alt Authority OK
    A2A-->>A: Result + receipt
  else Resolution-only
    A2A-->>A: Denied — resolution ≠ use
  end

Illustrative adapter (ports are real; DNTLS client/wire is external and not shipped):

import {
  createComposedResolver,
  type AgentResolutionProvider,
  type AgentServicePublicationV1,
} from '@agenticprimitives/agent-resolution';

// Ring-1: map DNTLS Service Record → AgentServicePublicationV1
// (agentId, channelId, sequence, surfaces[].uri/protocol, transportKeyBinding,
//  publishedBy, publicationAuthorityRef, digest, proofs[] — then ERC-1271 sign)
declare function mapDntlsRecord(record: unknown): AgentServicePublicationV1;
declare const externalDntlsClient: { resolve(id: string): Promise<{ record: unknown; proof: unknown }> };

const dntlsProvider: AgentResolutionProvider = {
  method: 'dntls',
  supports: (ref) => ref.kind === 'external' && ref.method === 'dntls',
  async resolve(ref, _ctx) {
    if (ref.kind !== 'external') throw new Error('unsupported');
    const { record, proof } = await externalDntlsClient.resolve(ref.identifier);
    return {
      method: 'dntls',
      referenceKind: 'external',
      publication: mapDntlsRecord(record),
      providerEvidence: [proof],
      servedAt: new Date().toISOString(),
    };
  },
};

const resolve = createComposedResolver({
  providers: [dntlsProvider],
  verifier: publicClient,
  // authorityCheck should also require AP facet → DNTLS commitment (bidirectional)
  authorityCheck,
  minAssurance: 'signed-publication',
});

const result = await resolve(
  { kind: 'external', method: 'dntls', identifier: 'treasury.ops.acme.dntls' },
  { requester: 'eip155:84532:0xaaa…', now: new Date().toISOString() },
  'eip155:84532:0xbbb…',
);
// result.ok ⇒ VerifiedAgentResolutionV1 — still no spend / tool permission

Full audit: dntls-comparison.md.

A hash proves unmodified. It does not prove current.

A signed card proves nobody tampered with a snapshot — not that it is still in force. So every publication carries a monotonic sequence, previousDigest, status, and expiresAt. Verification is fail-closed (rollback, equivocation, expiry, unauthorized publisher, missing endpoint-control proof, out-of-window transport keys):

import { verifyPublication } from '@agenticprimitives/agent-resolution';

const result = await verifyPublication(publication, {
  expectedAgentId: 'eip155:84532:0xacme…',
  now: new Date().toISOString(),
  verifier: publicClient,          // any { verifyHash } — a viem PublicClient fits
  authorityCheck,                  // "was this publisher allowed to publish for this agent?"
  known: continuity,               // what we already accepted on this channel
  requireEndpointProof: true,
  maxExposure: 'private',
});

if (!result.ok) {
  // Precise codes for YOUR logs; result.failures[].wireCode for anything you return to a caller.
  if (result.freshness.conflict) escalate('publisher equivocation — possible key compromise');
}

Equivocation — two validly signed publications at the same sequence — is reported, not merely rejected. It is evidence of publisher-key compromise, not a transient error.

Rotation is cheap; identity never moves

Endpoint change, transport-key rotation, regional failover, protocol bump, and provider migration all republish at sequence + 1. No grant is reissued and the canonical agent id does not change.

Private resolution grants, not private names

Salted private names are rejected (low-entropy secret, name becomes load-bearing). Grants are opaque high-entropy capabilities (apd1_…), recipient-bound:

ModeUse
subject-bound (default)Presenter proves subject SA possession — a copy is useless to others
pairwiseDistinct grant/projection/history per relationship
bearer-bootstrapShort-lived only until the recipient has an SA
const admission = await admitGrantPresentation(presentation, deps, {
  resolverAudience: 'https://resolve.acme.example/v1/private',
});
admission.projectionProfile; // 'partner' — what may be DISCLOSED, never invoked

Wire denials all use resolution_denied (no enumeration oracle); precise codes stay local.

Bootstrap, resolver, storage

Invitation = initial publication + grant + rendezvous + expected bindings (no re-invite on endpoint rotation). Org rendezvous reveals only that a private resolution service exists — replaceable, not the publication authority, cannot forge target-signed pubs or grant use. findOverDisclosure catches over-disclosure.

Owner vault (authoritative): pubs, grants, revocation, aliases. Resolver vault (ops only): keyed grant index, nonces, budgets — never the sole copy of anything that matters.

const digest = await deriveGrantDigest(grantId, resolverIndexSecret); // HMAC; 32-byte secret

Scope

Owns: discovery policy · publication verify · freshness · grants · invitations · projection · errors · provider ports. Not: transport, storage, clocks, authZ, naming, directory, search, profile, surface-catalog. Ring-0 (types only); ANS / rendezvous / DNTLS / DID are Ring-1.

Install

pnpm add @agenticprimitives/agent-resolution

License

MIT

版本与发布记录

@agenticprimitives/agent-resolution 共发布 21 个版本,首次发布于 2026/08/03;过去 12 个月发布了 21 个版本。

版本发布日期距今
0.0.0-alpha.21latest2026/10/2612 天前
0.0.0-alpha.202026/10/1722 天前
0.0.0-alpha.192026/10/1622 天前
0.0.0-alpha.182026/10/1622 天前
0.0.0-alpha.172026/10/1622 天前
0.0.0-alpha.162026/10/1622 天前

关于 @agenticprimitives/agent-resolution 的常见问题

@agenticprimitives/agent-resolution 是什么?

Provider-neutral agent resolution primitives: agent discovery policy, signed sequenced AgentServicePublication with anti-rollback verification, private resolution grants, connection invitations, audience projection, and resolution provider ports. Resoluti

如何安装 @agenticprimitives/agent-resolution?

在项目目录运行 npm install @agenticprimitives/agent-resolution,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@agenticprimitives/types(^1.0.0-alpha.45)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@agenticprimitives/agent-resolution 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@agenticprimitives/agent-resolution 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@agenticprimitives/agent-resolution 可以商用吗?

@agenticprimitives/agent-resolution 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@agenticprimitives/agent-resolution 的下载量有多少?

根据 npm 官方下载统计,@agenticprimitives/agent-resolution 在 2026/10/05 – 2026/11/03 这 30 天内被下载 3,366 次,日均约 112 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@agenticprimitives/agent-resolution 还在维护吗?

最新版本 0.0.0-alpha.21 发布于 2026/10/26(12 天前);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/08/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。