Skip to content

Integration patterns

agent-passport is the identity/attestation layer. Here's how to wire it into a real agent.

1. Enforce scopes at the tool boundary

Wrap each tool your agent can call so it requires a scope:

function guard(passport, scope, tool) {
  return async (args) => {
    assertScope(passport, scope);           // throws if not granted
    const result = await tool(args);
    return result;
  };
}

const sendEmail = guard(passport, 'email:send', rawSendEmail);

2. Log every action to an audit store

async function run(agent, action, tool, args) {
  const result = await tool(args);
  const proof = await signAction(agent, { type: action, target: args.target, params: args });
  await auditStore.append(proof);           // signed, tamper-evident
  return result;
}

Later, anyone can verifyAction(proof) to confirm which agent performed it.

3. Trust a set of operators

A verifier keeps an allow-list of operator DIDs it trusts, then:

const passport = await verifyPassport(passportJwt);
if (!trustedOperators.has(passport.operator)) throw new Error('untrusted operator');

4. Short-lived passports

Since did:key has no revocation, prefer short expiresIn (hours/days) and re-issue. For a revocable, long-lived setup, layer a status list on top or use a did:web operator — see the VC ecosystem (e.g. walt.id).

What this is not

  • It does not sandbox the agent's process or intercept syscalls.
  • It does not stop a malicious operator from over-granting scopes — trust is rooted in which operators your verifier accepts.