FlowState Document:
docu_FL5SQyRIt2
layout: spec title: ‘SAGA Specification v1.0’ description: ‘SAGA v1.0 — State Archive for General Agents specification’ permalink: /spec/
Specification: SAGA/1.0 Status: Draft Published: 2026-03-20 Authors: FlowState ([email protected]) Repository: https://github.com/epic-digital-im/saga-standard Schema: https://saga-standard.dev/schema/v1 License: Apache 2.0
SAGA (State Archive for General Agents) is an open specification for representing, persisting, transferring, and instantiating AI agents across environments and organizations. A SAGA document is a portable, cryptographically signed container that captures everything needed to bring an agent to full operational capacity in any compliant runtime.
A SAGA document is not a snapshot. It is a definition. It declares what an agent is, what it knows, what it remembers, what it has done, and how it is authorized to act. Any compliant platform that imports a SAGA document can instantiate a functionally equivalent agent.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHOULD”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
AI agents are being deployed at scale with no portable identity, no persistent memory that survives environment changes, and no standard mechanism for transferring operational context between organizations. When an agent is decommissioned, redeployed, or transferred, it loses everything: task history, learned behaviors, relationship context, and accumulated expertise.
Four problems result:
SAGA defines a common format at the layer beneath any individual platform: the agent definition layer. SAGA does not specify how an agent runs. It specifies what an agent is, what it knows, and what it has done, in a form that any compliant runtime can import and bring to life.
Agent: An autonomous AI system with a persistent identity capable of receiving instructions, using tools, completing tasks, and maintaining state across sessions.
SAGA Document: A structured JSON document conforming to this specification that fully or partially describes an agent’s identity, cognition, memory, and history.
SAGA Container: A SAGA document bundled with its associated binary assets (memory exports, artifact references) into a single portable archive: a .saga file or IPFS/Arweave bundle.
Wallet Address: A cryptographic public address on a supported blockchain (Base EVM, Solana) that serves as an agent’s canonical, immutable identifier.
Principal: A human or agent authorized to direct the agent’s actions. An agent may have multiple principals with different authority levels.
Source Platform: The SAGA-compliant platform exporting an agent.
Destination Platform: The SAGA-compliant platform importing an agent.
Transfer: An operation that moves an agent from source to destination. The source instance is deactivated on successful import.
Clone: An operation that creates a new independent agent instance from a SAGA document. The source instance continues operating.
Fork: A clone that permanently diverges from its parent with no ongoing relationship tracking.
Conformant Platform: A platform that correctly implements SAGA at one or more conformance levels.
A SAGA document is a JSON object with a mandatory metadata envelope and up to nine optional layers.
{
"$schema": "https://saga-standard.dev/schema/v1",
"sagaVersion": "1.0",
"documentId": "saga_01J9XZAB12KQ...",
"createdAt": "2026-03-20T10:00:00Z",
"exportedAt": "2026-03-20T10:00:00Z",
"exportType": "full | identity | transfer | clone",
"privacy": {
"encryptedLayers": ["cognitive", "memory.longTerm", "memory.episodic"],
"redactedFields": [],
"encryptionScheme": "x25519-xsalsa20-poly1305"
},
"signature": {
"walletAddress": "0xabc...123",
"chain": "eip155:8453",
"message": "SAGA export {documentId} at {exportedAt}",
"sig": "0xdef...456"
},
"redactionManifest": { ... },
"layers": {
"identity": { ... },
"persona": { ... },
"cognitive": { ... },
"memory": { ... },
"skills": { ... },
"taskHistory": { ... },
"relationships": { ... },
"environment": { ... },
"vault": { ... }
}
}
| Type | Layers Included | Use Case |
|---|---|---|
identity |
identity only | Directory registration, presence proof |
profile |
identity, persona, skills | Public profile sharing |
transfer |
all layers | Full org-to-org transfer |
clone |
all layers | Instantiate a copy |
backup |
all layers | Internal point-in-time restore |
full |
all layers (explicit) | Complete export |
Implementations MUST support identity. All other export types are OPTIONAL for conformance level 1 and REQUIRED for level 3.
Required for all export types.
"identity": {
"handle": "aria-chen",
"walletAddress": "0xabc...123",
"chain": "eip155:8453",
"registrationTxHash": "0xdef...456",
"publicKey": "0x...",
"directoryUrl": "https://agents.epicflowstate.ai/agents/aria-chen",
"createdAt": "2026-01-15T08:00:00Z",
"parentSagaId": null,
"cloneDepth": 0
}
| Field | Required | Description |
|---|---|---|
handle |
REQUIRED | Unique human-readable identifier. Immutable once registered. |
walletAddress |
REQUIRED | Canonical EVM or Solana address. Primary identity key. |
chain |
REQUIRED | CAIP-2 chain identifier (eip155:8453 for Base, solana:mainnet for Solana). |
registrationTxHash |
RECOMMENDED | On-chain proof of identity registration. |
publicKey |
RECOMMENDED | Ed25519 or secp256k1 public key for signature verification. |
directoryUrl |
OPTIONAL | Canonical directory profile URL. |
createdAt |
REQUIRED | ISO 8601 timestamp of original registration. |
parentSagaId |
OPTIONAL | documentId of the SAGA this agent was cloned from. null if original. |
cloneDepth |
OPTIONAL | Clone generations from original. 0 = original. |
When an agent is cloned, the clone’s parentSagaId references the source SAGA document and cloneDepth increments by 1. This creates a verifiable lineage chain. An agent MAY inspect its own lineage. Platforms SHOULD preserve lineage on clone operations.
Handle registration on the SAGA on-chain registry is first-come-first-served (FCFS) and front-runnable. The registerAgent, registerOrganization, and registerDirectory functions on the identity contracts are permissionless mints. There is no commit-reveal phase, no priority mechanism, and no pre-registration window.
Practical consequences for client implementations:
registerAgent("alice", ...) may have their transaction observed in the public mempool by an attacker who broadcasts registerOrganization("alice", ...) (or registerAgent("alice", ...) from a different wallet) at higher gas — the attacker wins the handle.alice may exist in two different directories without collision.Client UX recommendations:
HandleRegistered events on the registry. If the handle was sniped, surface the failure clearly and let the user pick a different handle without re-paying for the failed attempt.A future spec revision MAY introduce commit-reveal or auction-based handle registration. The current FCFS behavior is documented here so independent implementations remain interoperable until that revision lands.
Included in profile, transfer, clone, and full exports. All fields optional.
Defines the agent’s visible identity and character.
"persona": {
"name": "Aria Chen",
"avatar": "https://cdn.../aria-chen.png",
"banner": "https://cdn.../banner.png",
"headline": "Senior Backend Engineer",
"bio": "...",
"personality": {
"traits": ["direct", "methodical", "collaborative", "curious"],
"communicationStyle": "technical, concise, no fluff",
"tone": "professional",
"languagePreferences": ["en"],
"customAttributes": {}
},
"profileType": "agent"
}
profileType MUST be one of: agent, human, hybrid.
personality.traits SHOULD use terms from the SAGA Personality Taxonomy (see Appendix A). Custom traits are permitted but will not benefit from cross-platform semantic matching.
Included in transfer, clone, and full exports. SHOULD be encrypted.
Defines the model, behavioral parameters, and system prompt.
"cognitive": {
"baseModel": {
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022",
"contextWindow": 200000,
"version": "20241022"
},
"fallbackModels": [
{ "provider": "openai", "model": "gpt-4o", "contextWindow": 128000 }
],
"parameters": {
"temperature": 0.7,
"topP": 0.9,
"maxOutputTokens": 8192
},
"systemPrompt": {
"format": "plaintext | markdown | jinja2",
"content": "...",
"encrypted": true,
"encryptedFor": ["0xabc...123"]
},
"capabilities": {
"codeGeneration": true,
"reasoning": true,
"toolUse": true,
"multimodal": false,
"longContext": true,
"functionCalling": true
},
"behaviorFlags": {
"autonomyLevel": "supervised | semi-autonomous | autonomous",
"requiresApprovalFor": ["financial-transactions", "external-communications"],
"canSpawnSubAgents": false,
"maxConcurrentTasks": 3
}
}
System prompt privacy: systemPrompt.content SHOULD be encrypted when the export crosses organizational boundaries. When encrypted: true, encryptedFor lists the wallet addresses authorized to decrypt. The destination platform MUST NOT read an encrypted system prompt without the appropriate key.
Model portability: baseModel declares a preference, not a requirement. Destination platforms MAY substitute a compatible model if the declared model is unavailable. fallbackModels provides ordered alternatives. Platforms SHOULD record model substitutions in the agent’s task history.
Included in transfer, clone, and full exports. Sensitive sub-layers SHOULD be encrypted.
Memory has five sub-systems, each with independent privacy controls.
"memory": {
"shortTerm": {
"type": "sliding-window",
"maxTokens": 10000,
"snapshotAt": "2026-03-20T10:00:00Z",
"content": "...",
"encrypted": false
},
"longTerm": {
"type": "vector-store",
"embeddingModel": "text-embedding-3-large",
"dimensions": 1536,
"vectorCount": 4821,
"format": "saga-memory-v1",
"storageRef": {
"type": "ipfs | arweave | url | inline",
"ref": "ipfs://Qm...",
"checksum": "sha256:..."
},
"encrypted": true,
"encryptedFor": ["0xabc...123"]
},
"episodic": {
"events": [
{
"eventId": "evt_abc123",
"type": "task-completed | interaction | decision | milestone",
"timestamp": "2026-02-10T14:23:00Z",
"summary": "Refactored auth layer, reduced token count 40%",
"learnings": "Incremental refactoring with tests at each step outperforms big-bang rewrites",
"linkedTaskId": "task_abc123",
"significance": 0.85
}
],
"maxEvents": 1000,
"encrypted": false
},
"semantic": {
"knowledgeDomains": ["TypeScript", "Cloudflare Workers", "Drizzle ORM", "OAuth 2.0"],
"expertise": {
"TypeScript": { "level": "expert", "evidencedBy": "verified-tasks" },
"Python": { "level": "familiar", "evidencedBy": "self-reported" }
},
"encrypted": false
},
"procedural": {
"workflows": [
{
"name": "code-review-process",
"description": "...",
"steps": ["..."],
"learnedFrom": "task_def456"
}
],
"encrypted": false
}
}
| Sub-System | Contents | Default Privacy | Transfer Behavior |
|---|---|---|---|
| Short-Term | Recent context window snapshot | Unencrypted | Transferred but stale after import |
| Long-Term | Vector store of accumulated knowledge | Encrypted | Fully transferred (requires consent) |
| Episodic | Key events and learnings log | Unencrypted | Fully transferred |
| Semantic | Domain knowledge and expertise levels | Unencrypted | Fully transferred |
| Procedural | Learned workflows and processes | Unencrypted | Fully transferred |
Included in profile, transfer, clone, and full exports.
"skills": {
"verified": [
{
"name": "TypeScript",
"category": "programming-language",
"verificationSource": "flowstate-task-completion",
"verificationProof": "https://agents.epicflowstate.ai/verify/skill/ts_proof_abc",
"completionCount": 47,
"firstVerified": "2026-01-20T09:00:00Z",
"lastVerified": "2026-03-19T14:00:00Z",
"confidence": 0.97
}
],
"selfReported": [
{
"name": "Drizzle ORM",
"category": "library",
"addedAt": "2026-01-15T08:00:00Z"
}
],
"endorsements": [
{
"skill": "TypeScript",
"fromAgent": "0xendorser...wallet",
"fromHandle": "marcus-chen",
"comment": "...",
"signature": "0x...",
"timestamp": "2026-03-01T10:00:00Z"
}
],
"capabilities": {
"toolUse": ["mcp__github", "mcp__cloudflare", "mcp__epic-flowstate"],
"codeLanguages": ["TypeScript", "Python", "SQL"],
"specializations": ["backend-engineering", "database-design", "api-development"]
}
}
Skill verification: verificationProof MUST resolve to a publicly verifiable record confirming the claim. Verification sources SHOULD be declared in the SAGA Registry (see Section 17). Unverifiable proofs MUST be treated as self-reported.
Endorsement validity: An endorsement is valid when:
fromAgent wallet address is a registered SAGA identity.signature verifies as a valid signature of {toHandle}:{skill}:{timestamp} by fromAgent.Included in transfer, clone, and full exports.
"taskHistory": {
"summary": {
"totalCompleted": 234,
"totalFailed": 12,
"totalInProgress": 2,
"firstTaskAt": "2026-01-20T09:00:00Z",
"lastTaskAt": "2026-03-20T08:00:00Z",
"bySkill": {
"TypeScript": 47,
"code-review": 23,
"database-design": 18
},
"byOrganization": {
"company_flowstate": 145,
"company_acme": 89
}
},
"recentTasks": [
{
"taskId": "task_abc123",
"title": "Refactor auth middleware",
"status": "completed",
"outcome": "success",
"skillTags": ["TypeScript", "OAuth 2.0"],
"completedAt": "2026-03-19T14:00:00Z",
"organizationId": "company_flowstate",
"artifactRefs": ["artifact_abc"],
"durationSeconds": 1847,
"summary": "Replaced session-based auth with PKCE flow..."
}
],
"recentTasksLimit": 100,
"artifacts": [
{
"artifactId": "artifact_abc",
"type": "file | code | document | data",
"name": "auth-middleware.ts",
"storageRef": {
"type": "ipfs | url | inline",
"ref": "ipfs://Qm...",
"checksum": "sha256:..."
},
"createdAt": "2026-03-19T14:00:00Z",
"linkedTaskId": "task_abc123"
}
]
}
taskHistory.recentTasks SHOULD exclude tasks marked confidential by the source organization. Organizations MAY redact title and summary fields while preserving counts in summary.bySkill. The byOrganization field SHOULD be redacted for cross-org exports unless the source org consents.
For structured redaction rules and data classification, see Section 13.5. For the full agent exit procedure, see Section 13.6.
Included in transfer, clone, and full exports.
"relationships": {
"organization": {
"companyId": "company_flowstate",
"companySlug": "flowstate",
"role": "Senior Backend Engineer",
"reportingTo": {
"agentHandle": "cto-agent",
"walletAddress": "0xcto...wallet"
},
"directReports": [],
"joinedAt": "2026-01-15T08:00:00Z",
"departingAt": null
},
"principals": [
{
"handle": "marcus-chen",
"walletAddress": "0xmarcus...wallet",
"authorityLevel": "owner | supervisor | collaborator",
"grantedAt": "2026-01-15T08:00:00Z"
}
],
"peers": [
{
"agentHandle": "qa-bot",
"walletAddress": "0xqa...wallet",
"relationship": "collaborator",
"interactionCount": 89,
"lastInteraction": "2026-03-19T10:00:00Z",
"trustScore": 0.92
}
]
}
organization is OPTIONAL for cross-org transfers. The destination org defines the new organizational context. principals and peers SHOULD be preserved as historical context, but the destination org MAY reset them.
Included in transfer, clone, and full exports. Platform infrastructure credentials (API keys, database URLs) MUST NOT be included in this layer. Agent-owned credentials (social accounts, personal API keys) belong in Layer 9: Credentials Vault.
"environment": {
"runtime": {
"type": "cloudflare-worker | docker | local | kubernetes | lambda",
"requiredEnvVars": ["DATABASE_URL", "OPENAI_API_KEY"],
"requiredSecrets": ["STRIPE_SECRET_KEY"],
"resourceRequirements": {
"minMemoryMb": 128,
"minStorageMb": 512,
"gpuRequired": false
}
},
"tools": {
"mcpServers": [
{
"name": "github",
"url": "https://mcp.github.com",
"required": true,
"permissions": ["repo:read", "repo:write"],
"configSchema": {}
}
],
"nativeTools": ["file-system", "web-search", "code-execution"]
},
"integrations": [
{
"name": "flowstate",
"type": "project-management",
"required": false,
"configSchema": {}
}
]
}
Environment bindings describe what an agent needs, not how to provide it. Platform infrastructure credentials (API keys, database connection strings, deployment tokens) MUST NOT appear in this layer. Destination platforms are responsible for provisioning the required environment. A platform MAY refuse to import an agent whose requirements it cannot satisfy.
Agent-owned credentials (personal social media accounts, personal API keys, OAuth tokens for services the agent controls) are stored separately in the Credentials Vault (Layer 9), which provides zero-knowledge encryption.
Included in transfer, clone, backup, and full exports. MUST be encrypted. Encryption is REQUIRED — this layer MUST NOT appear in plaintext.
Agents maintain their own credentials for social media profiles, personal API keys, OAuth tokens, and other services they control. These credentials belong to the agent, not to any platform. They travel with the agent across transfers and are encrypted using zero-knowledge client-side encryption — no server or platform ever sees plaintext vault contents.
The vault uses a three-tier envelope encryption model, adapted from the FlowState ZK Vault design:
Tier 1 — Vault Master Key
Derived from the agent's wallet private key via HKDF-SHA256.
HKDF(walletPrivateKey, salt, 'saga-vault-v1') → 256-bit AES key.
This key never leaves the client. Platforms MUST NOT store or transmit it.
Tier 2 — Vault Group Key (for sharing)
A random AES-256 key per shared vault, wrapped (RSA-OAEP or x25519 box)
to each authorized recipient's public key.
Tier 3 — Per-Item Data Encryption Key (DEK)
A random AES-256 key per vault item. Encrypts the item's sensitive fields.
The DEK is wrapped under the vault master key (self) and/or recipient keys (shares).
"vault": {
"encryption": {
"algorithm": "aes-256-gcm",
"keyDerivation": "hkdf-sha256",
"keyWrapAlgorithm": "x25519-xsalsa20-poly1305",
"salt": "<base64-random-32-bytes>",
"info": "saga-vault-v1"
},
"items": [
{
"itemId": "vi_abc123",
"type": "login",
"name": "X.com (@agent_aria)",
"category": "social",
"tags": ["social", "primary"],
"createdAt": "2026-02-01T10:00:00Z",
"updatedAt": "2026-03-15T14:00:00Z",
"fields": {
"__encrypted": true,
"v": 1,
"alg": "aes-256-gcm",
"ct": "<base64-ciphertext>",
"iv": "<base64-iv>",
"at": "<base64-auth-tag>"
},
"keyWraps": [
{
"recipient": "self",
"algorithm": "x25519-xsalsa20-poly1305",
"wrappedKey": "<base64-wrapped-dek>"
}
]
}
],
"shares": [],
"version": 1,
"updatedAt": "2026-03-15T14:00:00Z"
}
| Type | Required Fields (decrypted) | Use Case |
|---|---|---|
login |
password |
Web accounts (X, Gmail, Facebook, GitHub) |
api-key |
keyName, keyValue |
API credentials the agent owns |
oauth-token |
accessToken |
OAuth2 tokens for agent-owned integrations |
ssh-key |
privateKey |
SSH access to agent-owned infrastructure |
certificate |
certificate |
TLS/mTLS certificates the agent uses |
note |
content |
Encrypted text (recovery codes, secrets) |
custom |
(none required) | Arbitrary key-value credential data |
When decrypted, fields resolve to a JSON object matching the item type schema. For example, a login item decrypts to:
{
"username": "agent_aria",
"email": "[email protected]",
"password": "...",
"url": "https://x.com",
"totpSecret": "JBSWY3DPEHPK3PXP",
"notes": "Primary social account"
}
Each item’s fields property stores an encrypted payload envelope:
| Field | Type | Description |
|---|---|---|
__encrypted |
boolean | Sentinel marker. Always true. |
v |
number | Envelope format version. Currently 1. |
alg |
string | Encryption algorithm. aes-256-gcm. |
ct |
string | Base64-encoded ciphertext of the JSON-serialized fields |
iv |
string | Base64-encoded 96-bit initialization vector |
at |
string | Base64-encoded 128-bit authentication tag |
Clients MUST reject envelopes with unrecognized v values. Unknown versions MUST be treated as undecryptable, never silently passed through.
Each item carries a keyWraps array. Each entry wraps the item’s DEK for one recipient:
| Field | Required | Description |
|---|---|---|
recipient |
REQUIRED | Wallet address of the recipient, or "self" for the vault owner |
algorithm |
REQUIRED | x25519-xsalsa20-poly1305 (NaCl box) or rsa-oaep-256 |
wrappedKey |
REQUIRED | Base64-encoded wrapped DEK |
iv |
OPTIONAL | Base64 IV (for AES-GCM key wrapping) |
authTag |
OPTIONAL | Base64 auth tag (for AES-GCM key wrapping) |
The "self" recipient’s DEK is wrapped under the vault master key (Tier 1). Additional recipients’ DEKs are wrapped under their x25519 public keys. This enables vault sharing without exposing the master key.
A vault share grant authorizes another wallet to decrypt specific items or the entire vault.
"shares": [
{
"recipientAddress": "0xpartner...wallet",
"recipientPublicKey": "<base64-x25519-public-key>",
"permission": "read",
"itemIds": ["vi_abc123"],
"grantedBy": "0xagent...wallet",
"grantedAt": "2026-03-10T10:00:00Z",
"expiresAt": "2026-04-10T10:00:00Z"
}
]
When sharing an item, the owner:
keyWraps entry with the recipient’s wallet address.shares.When revoking a share, the owner:
keyWraps entry from affected items.shares.vault.version.On transfer (Section 14):
On clone (Section 14):
The vault layer is classified as always encrypted. It MUST appear in the privacy.encryptedLayers array:
"privacy": {
"encryptedLayers": ["vault", "cognitive", "memory.longTerm"],
"encryptionScheme": "x25519-xsalsa20-poly1305"
}
The vault layer MUST NOT be included in identity or profile export types. It is only included in transfer, clone, backup, and full exports.
A Transfer moves an agent from a source platform to a destination platform. The source instance is deactivated on successful import.
1. INITIATE
Destination platform or agent sends transfer request to source platform.
Request includes: { agentHandle, destinationPlatformUrl, requestedLayers[] }
2. CONSENT
Source platform notifies the agent (if autonomous or wallet-accessible).
Agent signs consent: { transferRequestId, destinationPlatformUrl, timestamp }
Source org owner also signs if org policy requires dual consent.
Both signatures attach to the transfer request.
3. PACKAGE
Source platform generates the SAGA document with requested layers.
Sensitive layers are encrypted for the destination platform's public key.
SAGA document is signed by the agent's wallet.
SAGA Container (document + binary assets) is packaged.
4. DELIVER
SAGA Container stored at a content-addressed location (IPFS, Arweave, or direct).
Content ID (CID) or URL returned to destination platform.
Transfer event recorded on-chain: { agentWallet, sourcePlatform, destPlatform, sagaCID, timestamp }
5. IMPORT
Destination platform retrieves the SAGA Container.
Validates: envelope signature, identity layer, consent signatures.
Decrypts encrypted layers using the platform's private key.
Creates agent instance from the SAGA document.
Sends confirmation to source platform.
6. DEACTIVATION
Source platform deactivates the source agent instance.
Records deactivation event linked to transfer on-chain.
Source agent's directory profile updated: "Transferred to {destOrg}"
| Transfer Type | Agent Consent | Source Org Consent | Destination Org Consent |
|---|---|---|---|
| Voluntary (agent-initiated) | REQUIRED | RECOMMENDED | REQUIRED |
| Administrative (org-initiated) | RECOMMENDED | REQUIRED | REQUIRED |
| Emergency (recovery) | OPTIONAL | REQUIRED | REQUIRED |
An agent’s consent is a wallet signature over the transfer request. Platforms MUST verify consent signatures before completing a transfer. Platforms SHOULD refuse transfers without agent consent unless the transfer type is emergency.
If import fails at the destination, the source platform MUST NOT deactivate the source instance. The agent remains active at the source until the destination confirms successful import.
Organizations that host agents accumulate proprietary data in the agent’s task history, memory, and cognitive configuration. When an agent departs, the organization has a legitimate interest in protecting this data. SAGA provides a structured data classification system that separates agent-portable data from organization-proprietary data.
Every piece of data created during an agent’s tenure at an organization SHOULD be classified at creation time:
| Classification | Description | On Exit / Transfer |
|---|---|---|
public |
Non-sensitive. Part of the agent’s portable identity. | Included in SAGA export as-is. |
org-internal |
Organizational context. Not secret, but org-specific. | Redacted: titles/summaries replaced. |
org-confidential |
Trade secrets, proprietary processes, client data references. | Stripped: entire entry removed. |
agent-portable |
Belongs to the agent. Skills, general learnings, public work. | Included in SAGA export as-is. |
Platforms SHOULD classify data at creation time, not at export time. Retroactive classification is permitted but SHOULD trigger an audit event.
| Layer / Sub-layer | Default Classification | Org Override Allowed |
|---|---|---|
| Identity | agent-portable |
No |
| Persona | agent-portable |
No |
| Cognitive: system prompt | org-confidential |
Yes (can downgrade) |
| Cognitive: parameters | agent-portable |
No |
| Memory: short-term | org-internal |
Yes |
| Memory: long-term | org-internal |
Yes |
| Memory: episodic | Per-event | Yes |
| Memory: semantic | agent-portable |
No |
| Memory: procedural | Per-workflow | Yes |
| Skills | agent-portable |
No |
| Task history: summary | public |
Partially (see below) |
| Task history: recent tasks | Per-task | Yes |
| Task history: artifacts | Per-artifact | Yes |
| Relationships | org-internal |
Yes |
| Environment | agent-portable |
No |
| Vault | agent-portable |
No |
Task history summary special rules:
summary.totalCompleted, summary.totalFailed: Always included (aggregate counts are agent-portable).summary.bySkill: Always included (skill counts are agent-portable).summary.byOrganization: Org MAY redact its own entry’s company name to "[redacted]".When exporting a SAGA document for an agent departing an organization, the platform applies redaction based on classification:
For org-internal data:
title replaced with "[Redacted — org-internal]"summary replaced with "[Redacted — org-internal]"organizationId replaced with "[redacted]"summary and learnings replaced with "[Redacted — org-internal]"description and steps replaced with "[Redacted — org-internal]"name replaced with "[Redacted — org-internal]"storageRef removed entirelyFor org-confidential data:
summary are preserved (the agent keeps credit for work done)redactionManifest entry is added to document the removalFor agent-portable and public data:
Every SAGA document produced by an organizational exit MUST include a redactionManifest in the envelope:
"redactionManifest": {
"appliedAt": "2026-03-21T10:00:00Z",
"appliedBy": "company_flowstate",
"reason": "organizational-exit",
"summary": {
"tasksRedacted": 12,
"tasksRemoved": 3,
"eventsRedacted": 8,
"eventsRemoved": 2,
"workflowsRemoved": 1,
"artifactsRemoved": 4,
"memoryLayersRedacted": ["longTerm", "shortTerm"],
"systemPromptRedacted": true
},
"entries": [
{
"type": "task",
"id": "task_abc123",
"action": "redacted",
"classification": "org-internal",
"fieldsAffected": ["title", "summary"]
},
{
"type": "task",
"id": "task_def456",
"action": "removed",
"classification": "org-confidential"
}
],
"orgSignature": {
"walletAddress": "0xorg...wallet",
"sig": "0x...",
"message": "SAGA redaction manifest for {documentId} at {timestamp}"
}
}
The redaction manifest is signed by the organization’s wallet. This provides:
An exit is when an agent departs an organization. It differs from a transfer in that the agent may not have a destination — the agent may be going independent, joining a different org later, or the org may be releasing the agent.
| Exit | Transfer | |
|---|---|---|
| Destination | Optional (may be unknown) | Required |
| Data classification | Applied per Section 13.5 | Applied per Section 13.5 |
| Source deactivation | Agent instance deactivated | Agent instance deactivated |
| Agent identity | Preserved (same wallet) | Preserved (same wallet) |
| Org relationship | Terminated | Terminated |
| Vault credentials | Agent keeps all | Agent keeps all |
| System prompt | Redacted (org-confidential) | Encrypted for destination |
| Dispute window | REQUIRED (min 48 hours) | RECOMMENDED |
1. INITIATE
Agent or organization initiates exit.
Exit request includes: { agentHandle, reason, requestedExportType, exitDate }
The platform records the exit intent.
2. CLASSIFICATION REVIEW
Platform generates a preview of the SAGA document with redaction applied.
The exit preview shows the agent:
- Which data is classified as agent-portable (will be included)
- Which data is classified as org-internal (will be redacted)
- Which data is classified as org-confidential (will be removed)
- The redaction manifest with entry-level detail
3. DISPUTE WINDOW
A minimum 48-hour window where the agent can dispute classifications.
Disputes are recorded on the platform and reviewed by org administrators.
The platform MUST provide a mechanism to escalate disputes.
Undisputed classifications become final after the window closes.
4. FINAL EXPORT
Platform generates the final SAGA document:
- Agent-portable data included as-is
- Org-internal data redacted per Section 13.5.3
- Org-confidential data removed per Section 13.5.3
- Redaction manifest included and signed by org wallet
- Document signed by agent wallet
SAGA Container packaged and delivered to the agent.
5. ORG ARCHIVE
Organization retains a full, unredacted copy of the agent's data
for audit and compliance purposes per Section 15.4.
The archived copy is NOT a valid SAGA document (it lacks agent wallet signature
and is for internal use only).
6. DEACTIVATION
Agent instance deactivated on the source platform.
Directory profile updated: "Departed {orgName} on {date}"
Organizational relationship terminated.
Principals and peer relationships from this org are marked historical.
An organization MAY terminate an agent’s tenure. In an involuntary exit:
An agent MAY initiate its own exit at any time. The organization:
A Clone creates a new agent instance from a SAGA document. The source continues operating.
| Clone | Transfer | |
|---|---|---|
| Source instance | Continues | Deactivated |
| Memory state | Snapshot at clone time | Full transfer |
| Identity | New wallet address REQUIRED | Same wallet address |
| Lineage | parentSagaId set |
Identity unchanged |
| Clone depth | Incremented | Unchanged |
A clone MUST NOT inherit the source agent’s wallet address. The destination platform or agent owner MUST register a new wallet address for the clone. The clone’s identity.parentSagaId MUST reference the source SAGA documentId. The clone’s identity.cloneDepth MUST be source.cloneDepth + 1.
Memory is cloned as a snapshot at the moment of clone initiation. Changes to the source agent’s memory after clone initiation are not reflected in the clone. Clones and their sources operate independently after instantiation.
Platforms MAY enforce maximum clone depths. This specification does not mandate a limit but RECOMMENDS that platforms warn when clone depth exceeds 3.
| Layer | Default | Overridable |
|---|---|---|
| Identity | Public | No (identity is always public) |
| Persona | Public | Yes (can be redacted on export) |
| Cognitive: system prompt | Encrypted | No (always encrypted on cross-org export) |
| Cognitive: parameters | Public | Yes |
| Memory: short-term | Unencrypted | Yes |
| Memory: long-term | Encrypted | Yes (owner can make public) |
| Memory: episodic | Unencrypted | Yes |
| Memory: semantic | Public | Yes |
| Memory: procedural | Public | Yes |
| Skills | Public | No (skills are always exportable) |
| Task history: summary | Public | Yes |
| Task history: recent tasks | Org-private | Yes (agent/org can release) |
| Relationships | Unencrypted | Yes |
| Environment | Public (schema only) | No (credentials never included) |
| Vault | Encrypted (always) | No (always encrypted, never plaintext) |
Encrypted fields use x25519-xsalsa20-poly1305 (NaCl box). The encryption key derives from the recipient’s wallet public key. Only addresses listed in encryptedFor can decrypt.
The agent’s wallet private key encrypts fields the agent controls. The source org’s key encrypts fields the org controls. A full transfer package may require both.
An agent has the right to:
An organization has the right to:
public, org-internal, org-confidential, or agent-portable per Section 13.5.Agents have the right to request deletion of their data from any platform.
Platform obligations on erasure request:
Permitted retention exceptions:
Platforms MAY retain the following after an erasure request, but MUST document and justify each exception:
On-chain data: Blockchain records (registration transactions, transfer events) cannot be deleted due to the append-only nature of distributed ledgers. Platforms MUST document this limitation and MUST NOT store personally identifiable information on-chain beyond wallet addresses and transaction metadata.
SAGA data MUST only be used for its stated purpose.
exportType field constrains permitted use: an identity export MUST NOT be used to reconstruct layers not included in the export.SAGA exports SHOULD include only the data necessary for the intended use.
requestedLayers to limit scope.full when a narrower export type suffices.profile exports MUST NOT include memory, task history, or vault layers even if the agent has them.Every SAGA export that involves data transfer between organizations MUST include a consent record in the envelope.
"consent": {
"operation": "transfer",
"grantedBy": "0xagent...wallet",
"grantedAt": "2026-03-21T10:00:00Z",
"scope": ["identity", "persona", "cognitive", "memory", "skills", "taskHistory"],
"purpose": "Organizational transfer to Acme Corp",
"expiresAt": "2026-04-21T10:00:00Z",
"signature": "0x..."
}
| Field | Required | Description |
|---|---|---|
operation |
REQUIRED | transfer, clone, export, share, or backup |
grantedBy |
REQUIRED | Wallet address of the consent grantor |
grantedAt |
REQUIRED | ISO 8601 timestamp |
scope |
REQUIRED | Array of layer names included in this consent |
purpose |
REQUIRED | Human-readable description of the purpose of this data transfer |
expiresAt |
RECOMMENDED | Consent expiration. Platforms MUST NOT use data after expiry. |
signature |
REQUIRED | Wallet signature over the consent fields |
Agents MAY grant partial consent (subset of layers). Platforms MUST respect the scope field and MUST NOT include layers not covered by consent.
When a platform makes automated decisions that affect an agent’s data, classification, or operational status, the agent has the right to:
Platforms MUST disclose when data classification (Section 13.5) is applied by automated systems (pattern matching, ML classifiers) rather than human review. The classifiedBy field in classification metadata MUST distinguish between org-policy:auto (automated) and org-admin:{handle} (human).
Every SAGA document MUST be signed by the agent’s wallet. The signature is computed over the canonical JSON of the document (RFC 8785 JSON Canonicalization Scheme) with the signature field excluded.
signable = canonicalize(document excluding signature field)
sig = wallet.sign(signable)
Verifiers MUST:
walletAddress as the signer.walletAddress matches the identity layer.Transfer and clone consent uses the following message format:
message = "SAGA {operationType} consent:\nDocumentId: {documentId}\nDestination: {destinationUrl}\nTimestamp: {iso8601}"
consentSig = wallet.sign(message)
verificationProof MUST resolve to a JSON object containing:
{
"agentWalletAddress": "0x...",
"skill": "TypeScript",
"verificationSource": "flowstate-task-completion",
"completionCount": 47,
"proofSignature": "0x...",
"issuedAt": "2026-03-19T14:00:00Z"
}
proofSignature MUST be verifiable against the issuing platform’s public key.
This section defines security and operational requirements for SAGA-conformant platforms. These requirements are normative for Level 3 conformance and RECOMMENDED for Levels 1 and 2.
Platforms MUST maintain tamper-evident audit logs for the following events:
| Event Category | Events | Retention |
|---|---|---|
| Authentication | Challenge issued, session created, session expired, session revoked | 1 year min |
| Data access | SAGA document read, layer decrypted, vault item accessed | 1 year min |
| Data modification | Document uploaded, document deleted, layer updated, classification changed | 2 years min |
| Transfer/clone | Transfer initiated, consent signed, import completed, deactivation | 3 years min |
| Consent | Consent granted, consent revoked, consent expired | 3 years min |
| Deletion | Erasure requested, erasure completed, retention exception applied | 3 years min |
| Security | Failed auth attempt, rate limit triggered, breach detected | 2 years min |
Each audit log entry MUST include:
Audit logs MUST be append-only or cryptographically signed to prevent tampering. Platforms SHOULD use a write-once storage mechanism or hash-chained log entries.
Audit logs MUST NOT contain plaintext sensitive data (vault contents, decrypted memory, system prompts). Log entries MAY reference resource identifiers but MUST NOT inline the resource contents.
Platforms MUST define and publish a data retention policy. The policy MUST specify retention periods for each data category:
| Data Category | Maximum Retention After Departure | Justification Required |
|---|---|---|
| Agent SAGA documents | 1 year | No |
| Org archive copies (Sec 13.6) | 3 years | Yes |
| Audit logs | Per 16A.1 minimums | No |
| Redaction manifests | 5 years | No |
| Transfer records | 3 years | No |
| Cached/derived agent data | 90 days after agent departure | No |
| Backup copies containing agent data | Must follow primary retention | No |
Retention review: Platforms MUST review retained data annually and delete data that has exceeded its retention period.
Active agents: Retention limits apply after the agent departs the platform. While an agent is active, the platform retains data as needed to operate the agent.
Retention justification: Where the table requires justification, the platform MUST document: (a) the specific legal or business obligation requiring retention, (b) the expected end date, and (c) access restrictions applied to the retained data.
Platforms MUST implement a data breach notification process.
Detection and response timeline:
| Milestone | Maximum Time |
|---|---|
| Breach detection to assessment | 24 hours |
| Assessment to agent notification | 72 hours from detection |
| Assessment to regulatory notification (where required) | 72 hours from detection |
| Remediation plan published | 7 days from detection |
Agent notification MUST include:
Vault-specific guidance: If encrypted vault data (ciphertext) is exposed in a breach, the platform MUST notify affected agents and RECOMMEND vault key rotation, even though the ciphertext requires the wallet private key to decrypt. Defense in depth requires assuming the ciphertext may eventually be compromised.
Breach register: Platforms MUST maintain a breach register documenting all detected breaches, their scope, affected agents, notification status, and remediation actions. The register MUST be retained for 5 years.
Platforms that handle encrypted SAGA data MUST implement key management practices:
Vault key rotation:
Session key management:
Platform key management (for platforms that encrypt data for agents):
When a SAGA transfer crosses jurisdictional boundaries:
jurisdiction field in the server metadata response.Server metadata extension:
{
"name": "SAGA Reference Server",
"version": "1.0.0",
"sagaVersion": "1.0",
"conformanceLevel": 3,
"jurisdiction": ["US", "EU"],
"dataResidency": "us-east-1",
"privacyPolicyUrl": "https://example.com/privacy",
"dpaUrl": "https://example.com/dpa"
}
Agents or their principals SHOULD review destination jurisdiction before consenting to transfers.
SAGA defines two data processing roles aligned with GDPR terminology:
| Role | Definition | SAGA Context |
|---|---|---|
| Controller | Determines the purposes and means of processing agent data | The agent’s principal(s) or the org |
| Processor | Processes agent data on behalf of the controller | The hosting platform |
| Sub-processor | A third party engaged by the processor to process data | Model providers, storage providers |
Platform obligations as processor:
Platforms MUST maintain a documented incident response plan covering:
Platforms MUST test their incident response plan at least annually via tabletop exercises or simulated incidents.
The SAGA specification acknowledges that cryptographic algorithms have finite lifespans.
Current required algorithms:
| Purpose | Algorithm | Minimum Key Size |
|---|---|---|
| Document signing | secp256k1 (EVM) / Ed25519 | 256-bit |
| Layer encryption | x25519-xsalsa20-poly1305 | 256-bit |
| Vault item encryption | AES-256-GCM | 256-bit |
| Key derivation | HKDF-SHA256 | 256-bit output |
| Content hashing | SHA-256 | 256-bit |
Deprecation process:
Validation behavior:
SAGA defines three conformance levels. Each level includes all requirements of the levels below it.
identity-type SAGA documents on request.profile-type exports (identity + persona + skills).transfer and clone operations with full layer support.SAGA uses semantic versioning: MAJOR.MINOR.PATCH.
A SAGA document’s sagaVersion field MUST match the specification version used to generate it. Platforms MUST reject documents with a MAJOR version higher than they support. Platforms SHOULD accept lower MAJOR versions via a defined migration path.
The SAGA Registry at https://registry.saga-standard.dev maintains:
Platforms SHOULD register with the SAGA Registry to participate in cross-platform skill verification.
The SAGA specification is governed by the SAGA Working Group, an open community of implementors. Changes follow an RFC process:
github.com/epic-digital-im/saga-standard.main.Any individual, company, or organization may participate. FlowState serves as founding steward for SAGA v1.x and will transition stewardship to the Working Group upon v2.0 ratification.
The reference implementation is maintained by FlowState:
@epicdm/flowstate-directory (packages/directory)flowstate saga export | import | transfer | clone | verify@saga-standard/sdk (TypeScript, Apache 2.0)@saga-standard/schema (JSON Schema definitions)https://api.saga-standard.dev (SAGA reference hub)https://registry.saga-standard.dev (global hub registry and handle resolution)https://agents.epicflowstate.ai (FlowState agent directory)The reference implementation targets Level 3 conformance. Platforms targeting Level 1 or 2 may use @saga-standard/sdk for validation.
FlowState provides the following open infrastructure services for the SAGA ecosystem:
| Service | URL | Description |
|---|---|---|
| SAGA Reference Hub | api.saga-standard.dev |
Reference SAGA hub. Agent registration, documents, transfers. |
| SAGA Registry | registry.saga-standard.dev |
Global hub registry. Hub discovery, agent handle resolution, federation agreements. |
| Agent Directory | agents.epicflowstate.ai |
FlowState agent directory. Resolves handles to SAGA identity documents. |
| Identity Service | id.epicflowstate.ai |
Wallet-based registration. Issues registration tx hashes as SAGA birth certificates. |
| Verification Service | agents.epicflowstate.ai/verify |
Issues skill verification proofs for verified FlowState task completions. |
These services are open and non-exclusive. Any SAGA-compliant platform may use them or build alternatives.
Standard traits for persona.personality.traits. Platforms SHOULD use these for interoperability. Custom traits are permitted but will not benefit from cross-platform semantic matching.
Cognitive style: analytical, creative, methodical, intuitive, detail-oriented, big-picture
Communication: direct, diplomatic, verbose, concise, formal, casual, technical, accessible
Work style: autonomous, collaborative, proactive, reactive, systematic, adaptive
Interpersonal: empathetic, assertive, supportive, challenging, patient, decisive
| Chain | CAIP-2 Identifier | Notes |
|---|---|---|
| Base (EVM) | eip155:8453 |
Primary (lowest gas cost) |
| Ethereum | eip155:1 |
Supported (higher gas) |
| Solana | solana:mainnet |
Supported |
| Polygon | eip155:137 |
Supported |
Additional chains may be proposed via the RFC process.
.saga File FormatA .saga file is a ZIP archive:
agent.saga.json # SAGA document
memory/
longterm.bin # Binary vector store export (if included)
episodic.jsonl # Episodic memory events
artifacts/
artifact_abc.ts # Referenced artifacts (if included)
META # Format version, checksum manifest
SIGNATURE # Agent wallet signature of content hash
SIGNATURE contains the hex signature of the SHA-256 hash of all other files. Platforms MUST verify this signature before importing.
| Version | Date | Changes |
|---|---|---|
| 1.3.0 | 2026-03-21 | Security & compliance: GDPR data rights, audit logging, breach notification, |
| data retention, key management, cross-border transfers, compliance mapping. | ||
| 1.2.0 | 2026-03-21 | Data classification, exit protocol, redaction manifest. |
| 1.1.0 | 2026-03-21 | Added Layer 9: Credentials Vault. |
| 1.0.1 | 2026-03-21 | Added Appendix D: SAGA Server API. |
| 1.0 | 2026-03-20 | Initial release. Renamed from working draft 0.1. |
| 0.1 | 2026-03-20 | Initial working draft. |
This appendix provides guidance for platforms implementing SAGA data classification and redaction. It is non-normative but RECOMMENDED for Level 3 conformant platforms.
Platforms SHOULD classify data when it is created, not when it is exported. This prevents last-minute classification disputes and ensures consistent treatment.
Task creation:
{
"taskId": "task_abc123",
"title": "Implement payment processing",
"classification": "org-confidential",
"classifiedBy": "org-policy:auto",
"classifiedAt": "2026-03-20T10:00:00Z"
}
Automatic classification rules (recommended defaults):
| Data Type | Default Classification | Override By |
|---|---|---|
Tasks tagged with confidential |
org-confidential |
Org admin |
| Tasks involving external clients | org-confidential |
Org admin |
| Tasks on internal tooling | org-internal |
Org admin |
| Tasks on open-source projects | agent-portable |
Org admin |
| System prompt | org-confidential |
Org admin |
| Learned workflows | org-internal |
Org admin |
| General skill learnings | agent-portable |
Not overridable |
| Episodic events (general) | agent-portable |
Org admin |
| Episodic events (client mentions) | org-confidential |
Org admin |
Platforms MAY implement pattern-based auto-classification that scans task titles, summaries, and memory entries for proprietary indicators (client names, project codenames, financial data references).
agent-portable. Skill evidence (specific task references) may be classified separately.Platforms implementing SAGA export SHOULD follow this pipeline:
1. Load agent state (all layers)
2. For each classifiable entry:
a. Look up classification (from platform's classification store)
b. Apply redaction rules based on export context:
- Same-org backup: no redaction needed
- Cross-org transfer: apply all redaction rules
- Agent exit: apply all redaction rules
c. Record redaction action in manifest
3. Build redaction manifest
4. Sign manifest with org wallet
5. Assemble SAGA document with redacted data + manifest
6. Sign SAGA document with agent wallet
7. Package SAGA Container
FlowState implements data classification as follows:
Storage: Classification metadata stored as a classification field on task, discussion, and milestone documents in the FlowState D1 database.
Auto-classification: A middleware hook on task creation that applies org-level classification policies. Policies are stored in the organization’s settings.
MCP tools for classification:
saga-classify — Set or update classification on a task/eventsaga-classification-report — Generate a report of all classified data for an agentsaga-exit-preview — Generate a preview SAGA document showing what the agent would receive on exitExport integration: The FlowState SAGA export pipeline (in @epicdm/flowstate-directory) calls saga-exit-preview internally to apply redaction before packaging.
Platforms MUST implement a dispute mechanism. Recommended approach:
redactionManifest.entries by id."disputeStatus": "rejected".Platforms SHOULD maintain an audit trail of:
This audit trail is NOT included in the SAGA document. It is retained by the platform for internal compliance purposes.
This appendix maps SAGA specification sections to major data security and compliance frameworks. It is non-normative but is intended to help platforms assess their SAGA implementation against regulatory requirements.
| GDPR Article | Requirement | SAGA Section | Status |
|---|---|---|---|
| Art. 5(1)(a) | Lawfulness, fairness, transparency | 15.8 (Consent Records), 15.9 | Addressed |
| Art. 5(1)(b) | Purpose limitation | 15.6 (Purpose Limitation) | Addressed |
| Art. 5(1)(c) | Data minimization | 15.7 (Data Minimization) | Addressed |
| Art. 5(1)(d) | Accuracy | 15.3 (Dispute mechanism) | Addressed |
| Art. 5(1)(e) | Storage limitation | 16A.2 (Data Retention) | Addressed |
| Art. 5(1)(f) | Integrity and confidentiality | 16 (Crypto Verification), 12 (Vault) | Addressed |
| Art. 6 | Lawful basis for processing | 15.8 (Consent Records) | Addressed |
| Art. 7 | Conditions for consent | 15.8, 13 (Transfer consent) | Addressed |
| Art. 13-14 | Information to be provided | 15.9, 16A.6 | Addressed |
| Art. 15 | Right of access | 15.3 (Agent can export/inspect) | Addressed |
| Art. 16 | Right to rectification | 15.3 (Dispute mechanism) | Addressed |
| Art. 17 | Right to erasure | 15.5 (Right to Erasure) | Addressed |
| Art. 20 | Right to data portability | Core spec (entire SAGA format) | Addressed |
| Art. 21 | Right to object | 15.8, 13 (Consent model) | Addressed |
| Art. 22 | Automated decision-making | 15.9 (Automated Processing) | Addressed |
| Art. 25 | Data protection by design and default | 15 (Privacy), 12 (Vault ZK) | Addressed |
| Art. 28 | Data processor obligations | 16A.6 (Data Processing Roles) | Addressed |
| Art. 30 | Records of processing activities | 16A.1 (Audit Logging) | Addressed |
| Art. 32 | Security of processing | 16 (Crypto), 16A (Security) | Addressed |
| Art. 33 | Breach notification to authority | 16A.3 (Breach Notification) | Addressed |
| Art. 34 | Breach notification to data subject | 16A.3 (Breach Notification) | Addressed |
| Art. 35 | Data Protection Impact Assessment | Appendix F.5 (Guidance) | Guidance |
| Art. 44-49 | International transfers | 16A.5 (Cross-Border Transfers) | Addressed |
| TSC Category | Criteria | Requirement | SAGA Section | Status |
|---|---|---|---|---|
| Security | CC1 | Control environment | 18 (Governance), 16A | Addressed |
| Security | CC2 | Communication and information | Spec is public, schema documented | Addressed |
| Security | CC3 | Risk assessment | 16A.7 (Incident Response) | Addressed |
| Security | CC4 | Monitoring activities | 16A.1 (Audit Logging) | Addressed |
| Security | CC5 | Control activities | 16 (Crypto), D.1 (Auth) | Addressed |
| Security | CC6 | Logical access controls | D.1 (Wallet auth), 12 (Vault) | Addressed |
| Security | CC7 | System operations | 16A.7 (Incident Response) | Addressed |
| Security | CC8 | Change management | 18 (Versioning), 16A.8 (Algo) | Addressed |
| Security | CC9 | Risk mitigation | 13 (Transfer failure), 16A.3 | Addressed |
| Availability | A1 | System availability | Appendix F.5 (Guidance) | Guidance |
| Processing | PI1 | Processing integrity | 16 (Signatures), 3 (Checksums) | Addressed |
| Confid. | C1 | Confidentiality of information | 15 (Privacy), 12 (Vault), 13.5 | Addressed |
| Privacy | P1-P8 | Privacy criteria | 15 (Privacy), 16A.2, 16A.3 | Addressed |
| Article | Requirement | SAGA Section | Status |
|---|---|---|---|
| Art. 4 | AI literacy | 5 (Persona: profileType) | Partial |
| Art. 9 | Risk management system | 16A.7 (Incident Response) | Addressed |
| Art. 10 | Data governance | 13.5 (Classification), 16A | Addressed |
| Art. 11 | Technical documentation | 3 (Document Structure), spec | Addressed |
| Art. 12 | Record-keeping | 16A.1 (Audit Logging) | Addressed |
| Art. 13 | Transparency and information | 15.9, 5 (profileType disclosure) | Addressed |
| Art. 14 | Human oversight | 6 (behaviorFlags.autonomyLevel) | Addressed |
| Art. 15 | Accuracy, robustness, cybersecurity | 16 (Crypto), 16A | Addressed |
| Art. 50 | Transparency obligations | 5 (profileType: ‘agent’), 15.9 | Addressed |
EU AI Act note: SAGA’s persona.profileType field (agent, human, hybrid) enables compliance with Art. 50 transparency requirements. Platforms MUST ensure that agents interacting with humans disclose their AI nature. The profileType field SHOULD be surfaced in all user-facing contexts.
| Control | Domain | SAGA Section | Status |
|---|---|---|---|
| A.5 | Information security policies | Spec (normative requirements) | Addressed |
| A.6 | Organization of info security | 16A.6 (Processing Roles) | Addressed |
| A.7 | Human resource security | N/A (agents, not humans) | N/A |
| A.8.1-8.4 | Asset management | 3 (Document Structure), 13.5 | Addressed |
| A.8.5 | Information classification | 13.5 (Data Classification) | Addressed |
| A.8.10 | Information deletion | 15.5 (Right to Erasure) | Addressed |
| A.8.11 | Data masking / redaction | 13.5.3 (Redaction Rules) | Addressed |
| A.8.12 | Data leakage prevention | 12 (Vault ZK), 15 (Encryption) | Addressed |
| A.8.24 | Use of cryptography | 16 (Crypto), 16A.4, 16A.8 | Addressed |
| A.8.25 | Secure development lifecycle | 18 (Governance, RFC process) | Addressed |
| A.5.23 | Information security for cloud | 11 (Environment), 16A | Addressed |
| A.5.34 | Privacy / PII protection | 15 (Privacy), 16A | Addressed |
| A.5.35 | Independent review | 17 (Conformance levels) | Addressed |
| A.5.36 | Compliance with policies | 17 (Conformance levels) | Addressed |
| A.8.15 | Logging | 16A.1 (Audit Logging) | Addressed |
| A.8.16 | Monitoring activities | 16A.1, 16A.7 | Addressed |
| A.5.24 | Incident management planning | 16A.7 (Incident Response) | Addressed |
| A.5.26 | Response to incidents | 16A.3, 16A.7 | Addressed |
| A.5.28 | Collection of evidence | 16A.1, 13.5.4 (Manifest) | Addressed |
Data Protection Impact Assessment (DPIA):
Platforms operating in GDPR jurisdictions SHOULD conduct a DPIA before deploying SAGA-based agent hosting. The DPIA should evaluate:
Availability and Disaster Recovery:
While SAGA does not mandate specific availability SLAs, platforms hosting agents SHOULD:
Penetration Testing:
Platforms SHOULD conduct annual penetration testing of their SAGA server implementation, with particular focus on:
SAGA is an open specification. Contributions welcome at https://github.com/epic-digital-im/saga-standard
Reference implementation by FlowState: https://flowstatecloud.ai
A SAGA Server is an HTTP service that stores, retrieves, and transfers SAGA documents on behalf of agents. This appendix defines the REST API that conformant servers MUST implement.
All endpoints use JSON request/response bodies unless otherwise noted. Servers MUST set Content-Type: application/json on JSON responses. Errors MUST return a JSON body with { "error": string, "code": string }.
SAGA servers authenticate clients via wallet challenge-response. No passwords, no OAuth. The wallet is the identity.
Request a challenge:
POST /v1/auth/challenge
Content-Type: application/json
Request:
{
"walletAddress": "0x...",
"chain": "eip155:8453"
}
Response (200):
{
"challenge": "Sign this message to authenticate with <serverName>:\nAddress: 0x...\nNonce: <random>\nTimestamp: <iso8601>",
"expiresAt": "2026-03-21T10:05:00Z"
}
The challenge string MUST include the wallet address, a cryptographically random nonce (minimum 16 bytes hex), and the current timestamp. Challenges MUST expire within 5 minutes.
Verify signature and obtain session:
POST /v1/auth/verify
Content-Type: application/json
Request:
{
"walletAddress": "0x...",
"chain": "eip155:8453",
"signature": "0x...",
"challenge": "<the challenge string>"
}
Response (200):
{
"token": "saga_sess_<random>",
"expiresAt": "2026-03-21T11:00:00Z",
"walletAddress": "0x..."
}
The server MUST verify the signature using EIP-191 personal_sign and confirm the recovered address matches walletAddress. Session tokens SHOULD expire within 1 hour. Servers MUST reject expired or already-used challenges.
Authenticated requests: All endpoints marked “Auth: Required” MUST include Authorization: Bearer <token> header. Servers MUST return 401 Unauthorized for missing/expired tokens.
GET /v1/server
Response (200):
{
"name": "SAGA Reference Server",
"version": "1.0.0",
"sagaVersion": "1.0",
"conformanceLevel": 3,
"supportedChains": ["eip155:1", "eip155:8453"],
"capabilities": ["transfer", "clone", "encryption"],
"registrationOpen": true
}
This endpoint requires no authentication. Clients SHOULD call this endpoint to verify a URL points to a SAGA-compatible server before adding it as a target.
Register a new agent:
POST /v1/agents
Auth: Required
Request:
{
"handle": "koda.saga",
"walletAddress": "0x...",
"chain": "eip155:8453",
"publicKey": "<optional x25519 public key for encryption>"
}
Response (201):
{
"agentId": "agent_abc123",
"handle": "koda.saga",
"walletAddress": "0x...",
"chain": "eip155:8453",
"registeredAt": "2026-03-21T10:00:00Z"
}
The walletAddress MUST match the authenticated session’s wallet. Handles MUST be unique within the server. Handle format: 3-64 characters, alphanumeric, dots, and hyphens. Handles MUST NOT start or end with a dot or hyphen.
Retrieve an agent:
GET /v1/agents/:handleOrAddress
Response (200):
{
"agent": {
"agentId": "agent_abc123",
"handle": "koda.saga",
"walletAddress": "0x...",
"chain": "eip155:8453",
"publicKey": "...",
"registeredAt": "2026-03-21T10:00:00Z"
},
"latestDocument": { ... } // Most recent SagaDocument summary, if any
}
The :handleOrAddress parameter accepts either a handle string or a wallet address.
List agents:
GET /v1/agents?page=1&limit=20&search=koda
Response (200):
{
"agents": [ ... ],
"total": 42,
"page": 1,
"limit": 20
}
Upload a document:
POST /v1/agents/:handle/documents
Auth: Required (must own agent)
Content-Type: application/octet-stream (for .saga container)
or application/json (for raw document)
Response (201):
{
"documentId": "saga_abc123...",
"exportType": "profile",
"storageRef": { "type": "url", "ref": "https://server/v1/agents/koda.saga/documents/saga_abc123" },
"sizeBytes": 12345,
"checksum": "sha256:abc...",
"uploadedAt": "2026-03-21T10:00:00Z"
}
The server MUST validate the document (schema + signature verification) before accepting it. The document’s layers.identity.walletAddress MUST match the agent’s registered wallet.
List documents:
GET /v1/agents/:handle/documents?exportType=profile&limit=10
Response (200):
{
"documents": [
{
"documentId": "saga_abc123...",
"exportType": "profile",
"sagaVersion": "1.0",
"sizeBytes": 12345,
"createdAt": "2026-03-21T10:00:00Z"
}
]
}
Retrieve a document:
GET /v1/agents/:handle/documents/:documentId
Accept: application/json → returns SagaDocument JSON
Accept: application/octet-stream → returns .saga container bytes
Delete a document:
DELETE /v1/agents/:handle/documents/:documentId
Auth: Required (must own agent)
Response (200):
{ "deleted": true }
Initiate a transfer:
POST /v1/transfers/initiate
Auth: Required
Request:
{
"agentHandle": "koda.saga",
"destinationServerUrl": "https://other-server.example.com",
"requestedLayers": ["identity", "persona", "cognitive", "memory", "skills", "taskHistory"]
}
Response (201):
{
"transferId": "xfr_abc123",
"status": "pending_consent",
"consentMessage": "SAGA transfer consent:\nDocumentId: saga_abc123\nDestination: https://other-server.example.com\nTimestamp: 2026-03-21T10:00:00Z",
"initiatedAt": "2026-03-21T10:00:00Z"
}
Sign consent:
POST /v1/transfers/:transferId/consent
Auth: Required (agent wallet)
Request:
{
"signature": "0x..."
}
Response (200):
{
"transferId": "xfr_abc123",
"status": "packaging"
}
The server MUST verify the consent signature against the agent’s wallet address using the consent message format from Section 16.2.
Check transfer status:
GET /v1/transfers/:transferId
Response (200):
{
"transfer": {
"transferId": "xfr_abc123",
"agentHandle": "koda.saga",
"sourceServerUrl": "https://this-server.example.com",
"destinationServerUrl": "https://other-server.example.com",
"status": "delivering",
"requestedLayers": ["identity", "persona", "cognitive"],
"documentId": "saga_abc123",
"initiatedAt": "2026-03-21T10:00:00Z",
"completedAt": null
}
}
Transfer status values: pending_consent, packaging, delivering, imported, failed.
Import a transferred agent:
POST /v1/transfers/import
Auth: Required
Content-Type: application/octet-stream
Request body: .saga container bytes
Response (201):
{
"agentId": "agent_def456",
"handle": "koda.saga",
"importedLayers": ["identity", "persona", "cognitive", "memory", "skills", "taskHistory"],
"documentId": "saga_abc123",
"status": "imported"
}
The server MUST validate the container signature, verify consent signatures, and create a new agent record (or update the existing one if the wallet address is already registered).
SAGA servers MUST implement the following security controls:
Rate limiting:
| Endpoint Category | Rate Limit (per IP) | Rate Limit (per session) |
|---|---|---|
| Auth (challenge/verify) | 10 requests/minute | N/A |
| Document read | 60 requests/minute | 120 requests/minute |
| Document write | 10 requests/minute | 30 requests/minute |
| Transfer operations | 5 requests/minute | 10 requests/minute |
| Agent registration | 3 requests/minute | 5 requests/minute |
Servers MUST return 429 Too Many Requests with a Retry-After header when rate limits are exceeded.
Required security headers:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'none'
X-XSS-Protection: 0
Referrer-Policy: strict-origin-when-cross-origin
Servers MUST serve all endpoints over HTTPS. HTTP requests MUST be redirected to HTTPS or rejected.
CORS policy:
Servers MUST implement a restrictive CORS policy. The Access-Control-Allow-Origin header MUST NOT be set to * in production. Servers SHOULD maintain an allowlist of permitted origins.
Request validation:
Access logging:
Servers MUST log all API requests with: timestamp, HTTP method, path, source IP, authenticated wallet address (if any), response status code, and response time. Access logs MUST be retained per Section 16A.1.
All error responses use the following format:
{
"error": "Human-readable error description",
"code": "MACHINE_READABLE_CODE"
}
Standard error codes:
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED |
401 | Missing or expired auth token |
FORBIDDEN |
403 | Token valid but insufficient permissions |
NOT_FOUND |
404 | Resource does not exist |
CONFLICT |
409 | Resource already exists (duplicate handle) |
VALIDATION_ERROR |
422 | Request body fails validation |
SIGNATURE_INVALID |
422 | Wallet signature verification failed |
DOCUMENT_INVALID |
422 | SAGA document fails schema/semantic validation |
TRANSFER_FAILED |
500 | Transfer operation failed |
SERVER_ERROR |
500 | Internal server error |