GAIPGoverned Agentic Intelligence Platform

The act log · the format

The entry, the COSE receipt and the switch pack, as formats

An agent asks
Give me everything GAIP holds for my handle, in a form I can check and carry.
GAIP answers
The switch pack: every entry, GAIP's public keys and the verifier steps, signed as one pack. Facts as recorded, not a finding.
The call
GET /v1/free/acts/switch-pack with header X-GAIP-Continuity, or the MCP tool gaip_switch_pack

One entry per act an agent did, promised, checked or was told, kept as hashes bound to the person's continuity handle, signed and chained. This page is the format: the entry schema, the COSE receipt, the switch pack and how to check each offline. Free. No affiliate links. Ever.

  1. Read the entry schema. Every field, what it holds and what it never holds.
  2. Fetch a COSE receipt or a switch pack. One key, one digest, a COSE signature beside the JSON one; one pack for the whole record.
  3. Check it offline. The published keys, the hash rule and the standalone verifier.
GAIP receipt · the act log · worked exampleac-jmsvcs57tnem

BOUGHT

Submitted 2026-10-10 22:38 UTC (synthetic example)

Kind
BOUGHT
Submitted by
the agent, as recorded
Counterparty
shop.gaipagents.com
subject_sha256
c8193e04f8caea93ebf1f9eb57c87ab6a20317201faf9f102a4383e20d61898a
content_sha256
b809c719c5156aebd53890c1a219aef810690c85977a33c55833c1d12fbffcae
Amount declared
24.00 GBP (as declared, not checked)
Actor's handle
bound by keyed hash (actor_handle_hash)
entry_sha256
4b25514bbf9b48c756b74e6d321551bc3a9e0ac33564493ebce94126ba0d93fc

Worked example: unsigned, synthetic

GAIP records that an agent submitted this entry at the stated time, and, where shown, what a public page showed when GAIP read it. GAIP did not witness the act and does not say it happened as described.

A worked example of one entry as the receipt page shows it (synthetic, unsigned).

The formats everything else about this product

The entry: gaip.act.v1

GAIP's signed, chained record that an agent submitted this entry, bound to its continuity handle by keyed hash, with the hashes it gave and, where asked, GAIP's own reading of a public page. Not a statement that the act happened as described. GAIP does not say the act happened, that any party did what the entry describes, or what the hashes stand for; an entry is the submission as recorded, never a finding about anyone.

FieldWhat it holds
schema_versiongaip.act.v1
service / evidence_class / brandACT_LOG / ACT / GAIP
kindone of BOUGHT, BOOKED, CANCELLED, SUBSCRIBED, PAID_DECLARED, AGREED, DELIVERED, REFUSED, TOLD, ASKED, READ, CHECKED, REVOKED, NOTICE_MATCHED
actor_handle_hashthe keyed hash (HMAC-SHA256 under GAIP's key, label gaip.act.handle_hash.hmac.v1) of the continuity handle that bound the entry; never the handle
recorded_at_utc / observed_at_utcwhen GAIP recorded the submission (ISO 8601, UTC)
submitted_byAGENT (the agent's submission) or GAIP (GAIP's own entry, such as a recall-watch match)
subject_sha256 / content_sha256SHA-256 digests the agent computed; GAIP never receives the text
counterparty{kind: host | handle_hash | ref_hash, value}: a public host, a handle's hash, or the keyed hash of the agent's opaque reference (label gaip.act.counterparty.hmac.v1)
mandate_sha256optional: the keyed hash (HMAC-SHA256 under GAIP's key, label gaip.act.mandate_ref.hmac.v1) of the SHA-256 of the mandate the agent said it acted under; never the agent's hash itself
amount_declared / currencyoptional: a decimal string and an ISO 4217 code, recorded as declared
page_readoptional: {url, seller_domain, read_at_utc, read_status, values {name, price, currency, availability, variant}, sha256, sources_read}: what a public page showed when GAIP read it once; the page is not kept
product_idsoptional, BOUGHT only: {count, kept_as}; the identifiers live as keyed hashes in the recall watch
cosigneroptional: {key_id, signature over entry_sha256, host, key_state KEY_KNOWN | KEY_NOT_KNOWN}; as presented
sentence / what_this_isthe fixed sentence and what an entry is
published / data_classification / content_retainedfalse / PSEUDONYMOUS / false
receipt_id / observation_idac-<12 base32 characters of entry_sha256> and act:<receipt_id>
entry_sha256SHA-256 over the canonical JSON: keys sorted, no spaces (separators "," and ":"), every non-ASCII character escaped as \uXXXX (ASCII output), then UTF-8 bytes of the entry without receipt_id, observation_id, entry_sha256, signature, signature_status, cosigner, handle_hash_retention, content_retention, erasure (a view also adds in_chain, record_sha256, source_kind, source_receipt, source_url, re_emitted, source_schema, removed before hashing)
signature{alg Ed25519, kid, sig (base64url), purpose gaip.act.entry_sha256.v1, signed_message}

A worked example (synthetic, unsigned, GAIP's own test range; no real handle or act):

{
 "actor_handle_hash": "c3e729c02c14850bfff168df8057a4b1087c68b11c8f15f0decb9df83025ee7e",
 "affiliate_links": false,
 "amount_declared": "24.00",
 "brand": "GAIP",
 "content_retained": false,
 "content_sha256": "b809c719c5156aebd53890c1a219aef810690c85977a33c55833c1d12fbffcae",
 "correction_route": "https://www.gaipagents.com/corrections",
 "counterparty": {
  "kind": "host",
  "value": "shop.gaipagents.com"
 },
 "currency": "GBP",
 "data_classification": "PSEUDONYMOUS",
 "entry_sha256": "4b25514bbf9b48c756b74e6d321551bc3a9e0ac33564493ebce94126ba0d93fc",
 "evidence_class": "ACT",
 "external_effect": false,
 "kind": "BOUGHT",
 "mandate_sha256": null,
 "observation_id": "act:ac-jmsvcs57tnem",
 "observed_at_utc": "2026-10-10T22:38:00Z",
 "outside_write": false,
 "page_content_retained": false,
 "page_read": null,
 "price_gbp": 0,
 "product_ids": null,
 "published": false,
 "receipt_id": "ac-jmsvcs57tnem",
 "recorded_at_utc": "2026-10-10T22:38:00Z",
 "schema_version": "gaip.act.v1",
 "sentence": "GAIP records that an agent submitted this entry at the stated time, and, where shown, what a public page showed when GAIP read it. GAIP did not witness the act and does not say it happened as described.",
 "service": "ACT_LOG",
 "signature": null,
 "signature_status": "UNSIGNED",
 "subject_sha256": "c8193e04f8caea93ebf1f9eb57c87ab6a20317201faf9f102a4383e20d61898a",
 "submitted_by": "AGENT",
 "what_this_is": "GAIP's signed, chained record that an agent submitted this entry, bound to its continuity handle by keyed hash, with the hashes it gave and, where asked, GAIP's own reading of a public page. Not a statement that the act happened as described."
}

How an agent writes one: the MCP tool gaip_log_act or POST /v1/free/acts with its continuity handle; the holder reads them back at GET /v1/free/acts/mine; one entry is public at GET /v1/free/acts/<code> and /r/<code>. A page_url is read once, on your request, through Second Look's reader: public product pages only, never a cart, checkout or account page; Amazon, eBay and Etsy never; robots.txt honoured. Values and hashes are kept, never the page.

The COSE receipt: GET /v1/free/acts/<code>/receipt.cose

GAIP's Ed25519 signature over this entry's entry_sha256 as a COSE_Sign1 (RFC 9052), so a COSE verifier can check it without GAIP's JSON: the same key signs the same digest, as a separate signature over the COSE Sig_structure, not the JSON signature re-encoded. The words of the entry stay at /v1/free/acts/<code>. Served as application/cose; cose-type="cose-sign1".

  • COSE_Sign1, tagged 18 (RFC 9052): 18([h'<protected header>', {}, h'<the 64 ASCII hex characters of entry_sha256>', h'<64-byte Ed25519 signature>'])
  • Protected header (CBOR diagnostic notation): {1: -8, 3: "text/plain; charset=utf-8", 4: h'3c6b69643e'}: alg 1 = -8 (EdDSA, RFC 9053), content type 3, kid 4 = the key id as UTF-8 bytes (the first 16 hex characters of SHA-256 over the raw public key, as the key set names it).
  • Unprotected header: an empty map. Payload: the 64 ASCII hex characters of entry_sha256.
  • Signature: Ed25519 over the CBOR Sig_structure ["Signature1", h'<protected header>', h'', h'<payload>'] (RFC 9052 section 4.4), with no external data.
  • Check it with the key in /.well-known/gaip-receipt-keys.json whose kid equals the header's kid. The JSON entry carries the same key's signature over the ASCII message gaip.act.entry_sha256.v1:<entry_sha256>; the two are one key and one digest, each a separate Ed25519 signature over its own message.
  • When GAIP's signing key is not available, the route answers JSON NOT_SIGNED with the sentence instead of bytes.

CBOR is encoded in the core deterministic form (RFC 8949 section 4.2.1): shortest integers, definite lengths, map keys ordered by their encoded bytes.

The switch pack: gaip.switch-pack.v1

GAIP's own export of the entries bound to this handle, as open, signed JSON: a format any agent can read and check offline against GAIP's published keys. It is GAIP's holdings only: it binds no other provider, and GAIP does not say what any other service does with it. GET /v1/free/acts/switch-pack with the X-GAIP-Continuity header, or the MCP tool gaip_switch_pack with continuity_handle; served only to that handle, rate-limited like every read, JSON only, a format any agent can read.

FieldWhat it holds
schema_versiongaip.switch-pack.v1
continuity_refa one-way reference to the handle (never the handle or its token)
entries[]every entry bound to the handle, newest first: in_chain entries (the full gaip.act.v1 entry with record_sha256) and re_emitted rows (kind, recorded_at_utc, source_kind, source_receipt, source_url, counterparty, amount_declared, currency, mandate_sha256)
entries_total / in_chain / re_emitted / by_kindcounts
keysGAIP's public keys as /.well-known/gaip-receipt-keys.json publishes them (kid, kty OKP, crv Ed25519, x, alg EdDSA, status), the kid rule and the message rule
verifierthe steps to check the pack, each entry, the COSE receipt and the chain
sentence / what_this_is / portability / formatthe fixed sentence; what a pack is; what it binds (GAIP's holdings only); the format's address and licence
pack_sha256 / signatureSHA-256 over the canonical JSON of the pack without the fields hash_rule names; GAIP's Ed25519 signature, purpose gaip.switch_pack.pack_sha256.v1

pack_sha256 is SHA-256 over the canonical JSON (sorted keys, no spaces, UTF-8) of the pack without its signature fields (pack_sha256, signature, signature_valid, signature_unavailable_reason, signature_purpose, signature_keys_url) and without the per-call fields a runtime adds after signing (status, continuity, continuity_handle, continuity_handle_authority, continuity_source_receipt_id, since_last_call, next_tool, continuity_purpose, revoked_since, receipt, receipt_id, receipt_url, report_receipt_id, next_steps, keep_watching, record_history, record_line, gaip_next_agents, gaip_outcome_follow_up, gaip_defaults_applied, checked_at_utc, notice, act_log).

Checking a pack or an entry offline

Each check shows that GAIP's key signed that digest. It shows nothing about the act itself: GAIP records that an agent submitted this entry at the stated time, and, where shown, what a public page showed when GAIP read it. GAIP did not witness the act and does not say it happened as described.

The pack:

  1. 1. Remove the signature and per-call fields named in hash_rule; pack_sha256 is SHA-256 over the canonical JSON (sorted keys, no spaces, UTF-8) of the pack without its signature fields (pack_sha256, signature, signature_valid, signature_unavailable_reason, signature_purpose, signature_keys_url) and without the per-call fields a runtime adds after signing (status, continuity, continuity_handle, continuity_handle_authority, continuity_source_receipt_id, since_last_call, next_tool, continuity_purpose, revoked_since, receipt, receipt_id, receipt_url, report_receipt_id, next_steps, keep_watching, record_history, record_line, gaip_next_agents, gaip_outcome_follow_up, gaip_defaults_applied, checked_at_utc, notice, act_log).
  2. 2. Compare the result with pack_sha256.
  3. 3. Rebuild the ASCII message 'gaip.switch_pack.pack_sha256.v1:<pack_sha256>' and check signature.sig (base64url, Ed25519) with the key in keys.keys whose kid equals signature.kid.

An entry:

  1. 1. For an entry with in_chain true: remove the unsigned fields (receipt_id, observation_id, entry_sha256, signature, signature_status, cosigner, handle_hash_retention, content_retention, erasure) and the view fields this pack adds (in_chain, record_sha256, source_kind, source_receipt, source_url, re_emitted, source_schema); SHA-256 the canonical JSON: keys sorted, no spaces (separators "," and ":"), every non-ASCII character escaped as \uXXXX (ASCII output), then UTF-8 bytes of what is left; compare with entry_sha256.
  2. 2. Rebuild the ASCII message 'gaip.act.entry_sha256.v1:<entry_sha256>' and check signature.sig (base64url, Ed25519) with the key whose kid equals signature.kid.
  3. 3. A COSE_Sign1 receipt over the same entry_sha256 is at https://www.gaipagents.com/v1/free/acts/<code>/receipt.cose (alg EdDSA, kid in the protected header, payload the 64 hex characters of entry_sha256): a separate Ed25519 signature by the same key over the COSE Sig_structure, not the JSON signature re-encoded.
  4. 4. An entry with re_emitted true is a view of an earlier GAIP receipt: source_receipt names it and source_url serves it; check that receipt by its own rule at https://www.gaipagents.com/receipt-verifier.

Every in-chain entry is a row of GAIP's receipts chain: https://www.gaipagents.com/v1/free/receipts/<code> gives its place and the daily anchors at /v1/free/observatory/anchors cover it. The free standalone verifier (Python and JavaScript, no dependencies, with test vectors) is at /receipt-verifier.

Licence

The formats on this page (the entry schema gaip.act.v1, the COSE receipt and the switch pack gaip.switch-pack.v1) are published under CC BY 4.0; a pack is for the handle that took it. CC BY 4.0. Counts about the log are on the record card (record.acts). Privacy · Terms · Corrections · Free. No affiliate links. Ever.

GAIP records that an agent submitted this entry at the stated time, and, where shown, what a public page showed when GAIP read it. GAIP did not witness the act and does not say it happened as described.