Internal Attestations
Internal attestations are set by tools during workflow execution to prove that a step completed successfully. They enable sequential workflows where one operation must finish before another can begin.
Two attestations are not set by a tool and not approved by a person. The control plane mints them at registration, signed by the tenant attestor, from evidence only it can see. Require them like any other — add the name to attestations — with no approval_criteria and no approver. They answer different questions about the same login, and neither implies the other.
phishing_resistant — was a human present, and did they prove it with something unphishable? Minted from the token's amr / acr claims when the login used a passkey, WebAuthn, or a hardware key. Gate an approval tool on it and an agent holding a user's credentials can still call it, but cannot approve — it cannot produce a passkey ceremony. Expires with the token that produced it.
idp_verified — did the tenant's IdP vouch for this identity at all? Minted when registration validated a JWT. Gate a sensitive dataset on it and a self-reported agent never reaches it. Does not expire; revoked if the agent re-registers with a weaker identity.
An unverified login mints nothing rather than minting something that says "weak", so a gated tool denies by default.
Key Characteristics
Set by Tools
Internal attestations are created by tools as part of their execution. When a tool completes an operation, it can set an attestation to prove the operation occurred. It is kept for the caller whose call recorded it, in that service's memory: another caller or another service cannot use it, and it does not survive a restart.
Immediately Active
Unlike external attestations, internal attestations don't require approval. They become active immediately upon creation and can be consumed right away.
Supports max_uses
Internal attestations can specify how many times they can be used. After reaching max_uses, the attestation is automatically consumed.
No Approval Required
Internal attestations do not use approval_criteria. They are trusted because they come from authenticated tools within the workflow. Declare one with "internal": true in the policy that requires it. A tool's attestation never satisfies an approval or a built-in of the same name.
Fields Reference
| Field | Type | Description |
|---|---|---|
| key | string | Unique identifier for the attestation |
| value | any | Arbitrary data stored with the attestation |
| max_uses | int | Maximum times this attestation can be consumed |
| one_time | bool | If true, consumed after first use (equivalent to max_uses=1) |
| ttl | int | Time-to-live in seconds before expiration |
| use_count | int | Current number of times the attestation has been used |
| timestamp | float | Unix timestamp when the attestation was created |
Internal-Only Field
The max_uses field is only available for internal attestations. External attestations do not support this field - they useone_time instead for single-use behavior.
Setting Internal Attestations
A tool handler that declares a logger parameter receives the service's logger, and records an attestation with logger.attest():
# A tool handler
def read_file(params, logger):
# Perform the operation
data = load(params["path"])
# Record that the operation completed
logger.attest(
"file_read_complete",
value={"file": params["path"], "bytes": len(data)},
max_uses=3, # Can be used up to 3 times
ttl=3600 # Expires in 1 hour
)
return dataSingle-Use Pattern
# Attestation consumed after first use
logger.attest(
"payment_processed",
value={"transaction_id": "tx_123"},
one_time=True
)Multi-Use Pattern
# Attestation can be used 5 times
logger.attest(
"api_quota_token",
value={"remaining": 5},
max_uses=5
)Consuming Internal Attestations
Attestations are consumed automatically when a policy requires them. The policy engine checks for the attestation and decrements the use count:
{
"policy_id": "app:files",
"description": "Writing to a file requires reading it first",
"resources": ["tool:files/read", "tool:files/write"],
"constraints": {
"tool:files/write": { "attestations": ["file_read_complete"] },
"attestations": {
"file_read_complete": { "internal": true }
}
}
}Workflow Execution:
1. Tool A: read_file("/data/report.csv")
│
▼
Sets attestation: "file_read_complete"
(max_uses: 3, use_count: 0)
│
▼
2. Tool B: write_file("/data/report.csv")
│
▼
Policy checks: "file_read_complete" exists? ✓
Consumes attestation (use_count: 1)
│
▼
3. Tool C: write_file("/data/report.csv")
│
▼
Policy checks: "file_read_complete" exists? ✓
Consumes attestation (use_count: 2)
│
▼
...after 3 uses, attestation is consumed and removedLifecycle
┌─────────────────┐
│ Tool Execution │
└────────┬────────┘
│
▼
┌─────────────────┐
│ logger.attest( │
│ key, value) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ [Active] │
│ use_count: 0 │
└────────┬────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Consumed │ │ Consumed │ │ Expired │
│ (one_time) │ │ (max_uses) │ │(time_to_live)│
└─────────────┘ └─────────────┘ └─────────────┘Internal attestations are removed when they are fully consumed (all uses exhausted) or when their time_to_live expires, whichever comes first.
Common Use Cases
Sequential Workflows
Ensure operations happen in order. A write operation can require that a read operation completed first.
Validation Gates
A validation tool sets an attestation after checking data integrity. Downstream operations require the validation attestation.
Resource Quotas
Use max_uses to implement quota systems. An attestation grants N operations before requiring renewal.
Time-Limited Access
Use time_to_live to create temporary access windows. The attestation expires automatically after the specified duration.
Best Practices
- -Use descriptive keys: Name attestations clearly (e.g.,
file_read_completenotstep1) - -Include relevant data: Store information in the value that helps with auditing (file paths, hashes, timestamps)
- -Set appropriate time_to_live: Don't let attestations live forever. Set values that match your workflow timing
- -Use max_uses for quotas: When you need to limit how many times an operation can occur, use
max_uses - -Prefer one_time for single operations: Use
one_time=Trueinstead ofmax_uses=1for clarity