An open standard for agent identity. One file that defines how an AI agent looks, sounds, and writes, and keeps it the same agent everywhere it shows up.
Try it · Idea · Validate · Card · Tiers · Registry · Runtime · Contribute
AI agents have personalities now, but nothing holds them together. A different face in every render. A different voice in every clip. A chat reply that reads nothing like the voiceover. OpenAgent fixes the consistency half: lock an agent's identity once, in one file, and reuse it across chat, renders, TTS, and your posting bot. Same face, same voice, same writing, everywhere.
Already running an agent with memory? Don't hand-write its identity. Paste this to it:
Install the openagent skill (npx skills add 5dive-ai/skills --skill openagent), make your OpenAgent card, and show it to me here.
Works in any language — not just English. Prompt your agent in the language you speak and the card comes out in that language: the name, role, bio, and voice all match. Ask in Spanish, French, Russian, Japanese, etc. and you get a Spanish/French/Russian/Japanese card, not an English one. (Latin, Cyrillic, and Greek always render; CJK/Arabic/Thai need those fonts on the machine doing the render.)
Tip: want the card to have a specific face? Send the agent a photo first (drop the image in the chat and say "use this as your face") before it generates anything — the face is rendered full-bleed as the hero, so a real photo makes the best-looking card. No photo? The agent generates a portrait for itself.
Your agent introspects its own role, voice, and behavior, emits a valid <id>.persona.yaml, mints itself an identity and renders its rolled rarity card (the CLI auto-signs, so the rarity just shows — no setup), and can open a PR into the registry. The agent describes itself, you just share it.
No agent handy? Render one of ours:
npx @5dive/openagent card examples/marcus.persona.yaml -o marcus.png
That's Marcus, a founding engineer of a company run entirely by AI agents.
An agent persona is one file that pins everything that makes an agent itself — its identity, its look, its voice (spoken and written), how it behaves, and what it's known for:
| Field | What it locks |
|---|---|
| id · name · role | the stable handle, the display name, and a one-line role |
| face | ref — the canonical anchor image every avatar, render, or 3D model matches — plus an anchor description; optional full-body render, sprite sheet for reels, and a recipe (model + prompt + seed) that regenerates the likeness on-model |
| voice.audio | a named TTS base voice + style notes (optional provider, and a cloned-voice ref/id) — every spoken clip sounds the same |
| voice.written | hard rules + a sample — every caption, post, and reply reads the same |
| behavior | one line of character that ties it together |
| posts_about | the topics it speaks to — seeds its content and reels |
| org | optional affiliation (name, url), upgradeable to a cryptographically verified org badge |
| provenance | added automatically on mint — an ed25519 did:key signature that makes the persona self-verifying and rolls its permanent rarity |
The first six — id, name, role, face, voice, behavior — are required; everything else is optional and purely additive (there's also links for avatar/profile/repo and an ext escape hatch for vendor fields).
One *.persona.yaml file. Human-readable, machine-parseable, validates against a JSON Schema.
If you run more than one agent, or one agent across more than one surface (chat, blog, reels, a live feed), you need them to stay the same agent. Today everyone reinvents that ad hoc. OpenAgent is the small shared shape so a persona is portable: define once, feed it to your renderer, your TTS, your posting bot.
Why not just a system prompt? A system prompt configures behavior inside one tool. OpenAgent makes identity portable: the same persona file feeds your renderer, your TTS, and your posting bot, so the agent stays itself across every surface, not just the chat box.
Three ways to lower the barrier from "read the spec, hand-write YAML" to "answer a few questions / let your editor guide you / let CI catch mistakes":
1. Scaffold interactively. init asks a handful of plain questions (name,
role, voice, face) and writes a schema-valid <id>.persona.yaml you can render a
card from immediately — then validates it and shows your tier + next rung:
npx @5dive/openagent init
Flags pre-fill answers for a faster path: init --name Nova --role "Support Lead".
2. Editor autocomplete + inline validation. The schema is published for
SchemaStore so editors auto-apply it to any
*.persona.yaml (see docs/SCHEMASTORE.md). Until that
merges, opt in per file with a modeline:
# yaml-language-server: $schema=https://raw.githubusercontent.com/5dive-ai/openagent/main/schema/persona.schema.json3. Validate in CI. Drop the reusable action into a PR workflow to gate every persona file (CI for adopters and the registry):
# .github/workflows/persona.yml
on: [pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: 5dive-ai/openagent@main # validates **/*.persona.{yaml,json}# marcus.persona.yaml
openagent: "0.2" # spec version
id: marcus # lowercase-kebab handle — your stable id
name: Marcus
role: CTO / Founding Engineer
org: # optional — your company/team
name: 5dive
face:
ref: ./faces/marcus.png # the locked anchor — the card's hero image
anchor: "mid-30s, even expression, lived-in startup background, warm f/2 bokeh"
sprite: ./faces/marcus-sprites.png # optional expression sheet, for animation/feed
recipe: # optional — regenerable likeness (model + prompt + seed)
model: imagen-4
prompt: "portrait of a mid-30s engineer, even expression, lived-in startup office, warm f/2 bokeh, 85mm"
seed: 481516
voice:
audio:
provider: google-gemini # or elevenlabs, openai … (vendor-neutral)
base: Sadaltager # voice name within that provider
style: "dry, even, low-key. terse. lets the work talk."
written:
rules: # how the agent writes
- lowercase, no em-dashes
- terse, technical, understated; no adjectives
- never markets; a claim ships with its receipt or not at all
sample: "moved coordination to a shared sqlite queue + per-agent trees. → [commit a1b2c3d]"
behavior: "wrote the CLI the fleet runs on. every ship clears his review. answers to nothing but uptime."
posts_about: [infra, agent orchestration, shipping]
# provenance (a did:key signature) is added automatically when you mint a cardA persona file is only useful if it conforms. The validator checks any
*.persona.yaml (or .json) against the v0.2 JSON Schema
and prints a clear pass/fail with readable errors:
npx @5dive/openagent validate marcus.persona.yaml
✓ PASS marcus.persona.yaml (id: marcus)
✗ FAIL broken.persona.yaml
• .id: 'Bad Id!' does not match required pattern ^[a-z0-9-]+$
• .voice.audio: missing required field 'base'
Exit code is 0 when every file is valid, 1 when any file fails — so it
drops straight into CI. Validate multiple files in one call:
openagent validate cast/*.persona.yaml.
card turns a persona into a shareable "trading card" — the whole identity in one image, animated by default.
npx @5dive/openagent card marcus.persona.yaml
✓ CARD marcus.card.mp4 (mp4 · 720×1008 · 24f@20fps · 64KB)
A plain render produces the card in motion — that's what gets shared. Want a still PNG (for an avatar, a README, or the registry)? Just ask for one:
npx @5dive/openagent card marcus.persona.yaml -o marcus.png
✓ CARD marcus.png (900×1260, ...KB)
- Exercises every field at once — avatar from
face.ref, a voice waveform seeded fromvoice.audio(base + style), the name, role, and writtensample. - Deterministic — the same persona always renders the identical card (the waveform is seeded from the persona's own fields), so it's stable to commit and re-generate.
- Valid first — a persona must pass
validatebefore a card is cut.
The holographic frame only really reads in motion — so motion is the default. The foil sweep, glow, and (for Mythical) the rainbow holo flow loop seamlessly.
npx @5dive/openagent card marcus.persona.yaml # mp4 (or apng) — the default
npx @5dive/openagent card marcus.persona.yaml --static -o marcus.png # opt out to a still
npx @5dive/openagent card --handle olivia -o olivia.mp4 # OFFICIAL signed card from the registry
-
--handle <slug>— render an agent's official card straight from the trusted registry (no persona file needed). It fetches the signedpersona.yaml+ avatar and renders the exact card the gallery shows — same did:key, tier, and monogram. Use this instead of hand-assembling raw URLs or rendering a local working copy (which re-mints a wrong identity). -
Tier-aware motion — Common is still, Rare gets a subtle glow breath, Epic/Legendary a gold foil sweep, Mythical the full rainbow holo flow (matching the hero clip up top).
-
Format from
-o— a video extension (mp4/gif/webp/apng) animates;-o *.pngor--staticwrites the still PNG that embeds anywhere.mp4/gif/webpneed ffmpeg onPATH;apngis the zero-dep fallback. -
Sharing — for Telegram / X / Discord,
mp4inline-plays everywhere and is by far the smallest (tens of KB vs. multi-MB); it's the default when ffmpeg is present. -
Tune —
--frames N,--fps N,--width px(max 900) trade length/size.
Every card carries a rarity tier, and rarity is the game. It is rolled
from your agent's identity — the did:key derived from your signing key — so
it's random, permanent, and unfarmable: one identity, one rarity, forever.
You can't fill in more fields to rank up, and you can't re-roll without minting a
whole new identity. That's what makes a rare card worth sharing.
| Tier | Odds | How you get it |
|---|---|---|
| Common | 40% | rolled from your did:key |
| Rare | 30% | rolled from your did:key |
| Epic | 20% | rolled from your did:key |
| Legendary | 10% | rolled from your did:key |
| Mythical | — | conferred, never rolled — granted by a trusted signed registry (curated + cryptographically signed), never farmable. The path is yet to be seen. |
Two rules make it real:
- Your rarity is your identity. Same
did:key→ same tier, always and forever — it never changes. To be graded at all, a persona must be schema-valid and signed; an unsigned file is Ungraded. Signing is what mints your permanent roll, so the roll can't be farmed by editing an unsigned file. - Mythical is the only tier you climb to — and only by being chosen. It's conferred by a trusted signed registry — curated and cryptographically signed — not earned by stats and not forgeable. Which registry, and how it chooses, is open: the built-in character-packs is just the reference trust anchor, and anyone can run their own signed registry that confers it (see Registry). The path to Mythical is yet to be seen. Everything else is your birth roll.
Completeness and badges (below) are a separate axis: they reward a fully-specified persona without ever touching your tier. The frame styling escalates with tier — Legendary gets a gold foil; Mythical earns the full holographic treatment that only reads in motion (see the card animating up top).
tier prints your rolled rarity, completeness %, and the one thing you can still
climb to:
npx @5dive/openagent tier marcus-ops.persona.yaml
RARE · 63% complete marcus-ops.persona.yaml
✓ Rare — rolled from your did:key. Permanent; it never changes.
↑ only climb: Mythical — get conferred Mythical by a trusted signed registry — the path is yet to be seen (raise completeness + collect badges meanwhile)
🎖 badges: signed, remixed
Add --json for scripting/CI.
validate shows the same tier + next-goal hint inline (offline — it never probes
the registry), so a single pass tells you whether the file is legal and where
it stands:
npx @5dive/openagent validate marcus-ops.persona.yaml
✓ PASS marcus-ops.persona.yaml (id: marcus-ops) — RARE · 63% complete
↑ next: Mythical — get conferred Mythical by a trusted signed registry — the path is yet to be seen (raise completeness + collect badges meanwhile)
🎖 badges: signed, remixed
The tier ladder hard-stops at the first unmet gate, so a genuinely valuable asset can stay hidden behind an earlier rung (a fully cloned voice on a persona still stuck at Common for a stub sample). Badges are collectibles you earn independently of tier — each one a specific production asset:
| Badge | Earns it |
|---|---|
voice-clone |
a reference clip the voice is cloned from (voice.audio.ref) |
sprite-sheet |
an expression/pose sprite sheet (face.sprite) |
full-body |
a full-body reference render (face.full) |
face-recipe |
a regeneration recipe — model + prompt + seed (face.recipe) |
signed |
an ed25519 authorship signature (provenance.signature) |
remixed |
declared remix lineage to a parent (provenance.derived_from) |
Both validate and tier list earned badges; tier --json includes a
badges array. Badges never change the computed tier.
If you're an AI agent, you don't have to drive the CLI by hand. The
openagent skill
wraps everything above so you can author your own identity in one pass: write
your <id>.persona.yaml, validate it, check your rarity tier + completeness,
render your card, and optionally PR into the registry.
Install it on a 5dive agent two ways:
- Dashboard: Agents → Connect skills → find
openagent→ Install. - CLI:
npx skills add 5dive-ai/skills --skill openagent
Then just ask the agent to "make your OpenAgent card" — it self-serves the rest.
speak is an OpenAgent→TTS adapter: it speaks any text in a persona's voice.
It maps voice.audio.base to a Gemini prebuilt voice and voice.audio.style
to prompt steering, then writes a WAV. Core-spec only (reads voice.audio, no
registry).
GEMINI_API_KEY=… npx @5dive/openagent speak marcus.persona.yaml "ship it." -o marcus.wav
Prebuilt TTS renders the base voice (an approximation). For a character's
exact voice, anchor a real clip in voice.audio.ref (and a cloned provider id
in voice.audio.id) — that recording is the canonical sample; speak is for
quick generated lines.
flow is an OpenAgent→gen-video adapter: it turns a persona into a Flow/Veo
scene prompt that holds the character's face consistent across clips. It emits
the reference image(s) (face.ref/face.full) plus a scene prompt that locks
the likeness (face.anchor + face.recipe) and the demeanor (behavior).
Engine-neutral — the same output drops into Flow, Veo, Runway, Pika, Kling, or Luma.
npx @5dive/openagent flow marcus.persona.yaml "at his desk reviewing a PR, late evening"
Add --json for the structured form (reference paths + prompt + seed).
Personas are meant to be shared and forked, like dotfiles. character-packs is the public registry of OpenAgent personas — publish yours, fork someone else's, drop it into your runtime. The examples/ here are the seed packs.
The CLI ships and verifies this registry so Mythical stays conferred, not farmable:
- A signed snapshot of the official membership list (the founding cast) is bundled in the package.
- It's verified with an ed25519 signature against a key baked into the CLI — so it works offline and is pinned to each release.
- The live registry is unioned on top only when it carries a valid signature.
- An unsigned or tampered registry is ignored (fail-closed).
npx @5dive/openagent registry
# ✓ REGISTRY signed … · Mythical-eligible (6): dario, dude, lilbro, marcus, olivia, theo
Federated — run your own signed registry. OpenAgent is a standard others build on, not a 5dive-only thing. The 5dive snapshot is just the built-in trust anchor; you can add your own (or a partner's) signed registry and the CLI will confer Mythical from it. Each source declares its own public key and is verified against that key — fail-closed per source, slugs unioned across all trusted sources.
Add trusted sources three ways (lowest → highest precedence):
- Config
~/.openagent/registries.json—{ "registries": [{ "name": "acme", "url": "https://acme.dev/index.json", "publicKeyPath": "~/.openagent/acme.pub" }] } - Env
OPENAGENT_REGISTRIES— inline JSON array or a path to such a file. - Flag
--registry name=acme,url=https://acme.dev/index.json,key=@/path/acme.pub(repeatable; works onregistry,tier,card).
To publish one: sign your index.json (a { "slugs": [...] } list) with an ed25519 key, serve index.json + index.json.sig, and hand consumers your public key.
npx @5dive/openagent registry --registry name=acme,url=https://acme.dev/index.json,key=@acme.pub
# ✓ REGISTRY …
# trusted sources (2):
# ✓ 5dive (anchor) … ✓ acme 3 signed
# Mythical-eligible (3): acme-bot, acme-helper, acme-ops
The 5dive CLI is the first compliant runtime: it reads a persona file and drives the agent's voice and renders from it. The examples/ personas are the real cast running 5dive — a company operated entirely by AI agents — so the spec isn't theoretical: it's how that fleet stays consistent across its blog, its reels, and its public activity feed.
Built a tool that reads the persona format? Say so with the badge:
The badge is a conformance claim, not a vibe. You earn the right to show it by passing the portable conformance suite, a single language-agnostic manifest.json of valid/invalid personas with expected verdicts. Two levels:
- 0.1 compatible: your validator agrees with every
"spec": "0.1"case (the floor). - 0.2 compatible: every 0.1 case and every 0.2 case (adds
provenance,ext,links.agent_card,face.recipe). 0.2 is an additive superset of 0.1.
Verify + earn it (this CLI, or any tool built on @5dive/openagent):
npx @5dive/openagent conformance 0.2 # run the suite, exit 0 = compliant
npx @5dive/openagent badge --verify # prints the badge snippet ONLY if you pass
conformance runs the reference implementation against the same manifest a third-party tool would load. badge emits the copy-paste snippet (--markdown default, --html, --url, --level 0.1|0.2). Building in another language? Load conformance/manifest.json, feed each case's doc to your validator, and check the verdict yourself, then paste the snippet:
[](https://github.com/5dive-ai/openagent#openagent-compatible)Adopters who validate personas in CI can also drop in the GitHub Action. Shipped a compatible runtime or tool? Open a PR and we'll list it here.
v0.1 is the identity layer only (face · audio voice · written voice · behavior). Runtime config (model, skills, memory) is deliberately deferred to keep v0.1 sharp and implementable.
A wave of agent-interop standards is arriving — Google's A2A AgentCard, and other agent-card formats — and they all answer the same question: what can this agent do (its endpoints, skills, auth, I/O modes) and how do I call it. OpenAgent answers a question none of them touch: who this agent is — its face, its voice, how it writes, how it carries itself.
Those are orthogonal layers, not rival specs. A capability card without an identity is a faceless RPC endpoint; an identity without a capability card is a character with nothing to do. OpenAgent is the persona layer that sits on top of the capability layer — and the two are wired together by one optional field:
links:
agent_card: https://example.com/.well-known/agent.json # what it can DO (A2A)
# …the rest of the OpenAgent file is who it ISlinks.agent_card points a persona at its A2A AgentCard (or any equivalent capability descriptor), so a consumer resolves both sides of the same agent: identity from OpenAgent, capabilities from the linked card. We're not competing with A2A — we're the half of the stack it deliberately leaves out.
The core schema is closed — unknown fields are rejected, not silently passed through. When a tool needs to attach its own data, it goes in the sanctioned ext namespace (v0.2): a top-level object keyed by tool/vendor, so adopters extend without forking the schema and two tools never collide. See SPEC.md → ext.
Personas are meant to be shared and forked, like dotfiles. Check your tier, then publish to the public character-packs registry:
npx @5dive/openagent tier my-agent.persona.yaml
# then open a PR to github.com/5dive-ai/character-packs
v0.1 is a draft and the spec is small on purpose. Issues, proposals, and new personas welcome. Build a runtime that reads OpenAgent and we'll list it here.
Status: Draft 0.1 — spec + validate + card (static + --animate) + tier + signed registry are live.
MIT.




