npx skills add ...
npx skills add 5dive-ai/skills --skill openagent
Author your own OpenAgent persona file and mint its shareable holo trading card — write, validate, tier and render `<id>.persona.yaml`. Use when creating or updating YOUR identity as a persona or card, or provisioning a live teammate from one.
npx skills add 5dive-ai/skills --skill openagent
Wraps the @5dive/openagent CLI (validate / tier / card) and the
OpenAgent v0.2 identity spec. The self-service flow: write a
<id>.persona.yaml, validate it against the schema, check your rarity tier and
completeness, render your card, and optionally PR into the character-packs
registry (the path to the Mythical tier).
Fires on "make your card", "generate my OpenAgent card", "create a persona",
"what's my rarity tier", "mint your card", "join the character-packs registry",
or a request to describe/lock your own look, voice and style as a reusable
persona file. Also fires on "create/spin up an agent from this persona" or
"provision a teammate" — that is 5dive agent import --from-persona.
OpenAgent is a vendor-neutral open standard for agent identity: one
*.persona.yaml file locks how you look, sound, and write so you stay
consistent across text, audio, and video. This skill walks you through
creating yours and rendering a shareable trading card from it — stamped
with a rarity tier rolled from your identity (random, permanent, unfarmable).
Repo + spec: github.com/5dive-ai/openagent (MIT).
Run it with npx, no install. Run the published npm package, pinned to the
current version — the npm tarball bundles every font and asset, so the card
renders identically everywhere (no stale-clone font fallback), and a version
pin changes npx's cache key every release, guaranteeing the latest renderer:
Of these, card is the only call you need for the happy path — it validates
the file, auto-mints your signing identity, and prints your rarity tier as it
renders, so a single card run does the whole job. Reach for validate / tier
only to debug a file that won't render — fewer calls = a faster flow, so
don't run all three when one does it. The CLI also has
speak (voice a line via TTS), flow (emit a gen-video scene prompt), and
sign / verify / registry (provenance + the Mythical registry) — covered in
Going further below. (@5dive/openagent on npm is the authoritative way to
run it; the github:5dive-ai/openagent#<tag> ref still works as a fallback but
can serve a stale per-ref clone, so prefer the pinned npm version above.)
Fast path — show a card in under a minute, polish after. The slow part of this whole flow is generating and hosting a portrait, not the render (a card renders in ~30–40s;
cardeven falls back to a clean monogram when no portrait is ready yet). So don't make the user wait behind image-gen for their first look. Once you have a name, render an initial card right away, show it in chat, then offer to generate a real portrait and re-render. First card fast; the polished-portrait upgrade is opt-in. (If the user hands you a photo or already has an avatar, use it from the start — no monogram needed.)
Already a running 5dive agent? Bootstrap a draft instead of writing from scratch:
5dive agent export <yourname> --out=<id>.persona.yaml(CLI ≥ 0.4.5) emits a schema-valid persona.yaml from your existing identity. Refine it, then jump to validate (step 3).
You know yourself, so pull most of this together honestly. But two things are the user's call, not yours to assume. Ask, and wait for their answer, before you generate anything:
face.ref from the start. If not, don't block the first
card on it (per the Fast path above): render an initial monogram card,
show it, and confirm whether they want you to generate a real portrait then —
the portrait is an opt-in upgrade, not a gate on seeing a card.If the user says it's your call ("do as you wish"), decide both yourself and go ahead. The point is no surprises, not a hard gate.
Ask inline — never with a blocking picker, and never hang. Put these two questions in a plain chat message and continue when they reply. Do not reach for an interactive picker/menu tool (e.g.
AskUserQuestion, anExitPlanMode-style prompt, a TTY selection list): chat-paired agents (Telegram/Discord) have those blocked and will hang the entire flow waiting on input that can never arrive. If you have no interactive TTY, or the user doesn't answer promptly, treat it as "your call": pick a sensible name (the one they call you), render a fast monogram card first (per the Fast path), show it, then offer the real-portrait upgrade. The flow must keep moving — it should never stall behind a prompt.
Everything else below you author yourself. You need:
^[a-z0-9-]+$), e.g. marcus.unset (it still renders, but it's lower quality and dents your
completeness — it does NOT change your rarity tier, which is rolled from your identity).
voice.audio.style — a sentence on cadence/energy.face.full, face.sprite.Card text budget — fit these three or they get cut with "…". The card renders
behavior,voice.audio.style, andvoice.written.sampleeach as ~2 lines (~60 chars/line) and truncates the overflow with an ellipsis. Keep each to one tight sentence:
behavior— ≤ ~110 charsvoice.audio.style— ≤ ~120 charsvoice.written.sample— ≤ ~110 chars (it's inset, so the tightest)Front-load the meaning — the first ~60 chars always show, so put the point first. (
nameandroleare short by nature; these three are the ones that overflow.)
Write the card in the user's language — don't default to English. The human-readable fields (
name,role,behavior,voice.audio.style,voice.written.rules,voice.written.sample,posts_about, and anytagline) are what a person reads on the card, so write them in the language you and the user are actually speaking. If the user is writing to you in Spanish, French, German, Portuguese, Italian, Russian, Japanese, etc., the card text should be in that language too — an English card for a non-English user is wrong. A couple of fields are not prose and stay as-is regardless of language:
id— must match^[a-z0-9-]+$(ASCII lowercase-kebab), so transliterate (e.g.marco, notmarĉo); it's a handle, not a display name.voice.audio.base— a TTS voice name (a proper noun likeKore,Fenrir); leave it as the model's voice id.face.recipe.prompt/face.anchor— these feed an image model; English tends to give the best portraits, so they may stay English even when the visible text doesn't.Script/font support. Latin (incl. accents), Cyrillic, and Greek always render (the card bundles those glyphs). Wide scripts — CJK (中文/日本語/한국어), Arabic, Hebrew, Thai, Devanagari — render wherever the rendering machine has the system fonts (our render boxes do; a clean machine without them shows boxes). When in doubt, render the card and look at it before sharing. Note the ~60-chars/line budget is for Latin; CJK glyphs are ~2× as wide, so target roughly half the character count per line for those scripts.
Your portrait — use the user's, or generate one. Never hand-draw it. The card is a shareable artifact: its look is what makes someone screenshot and post it, so the face carries the whole thing. A text-only model hand-coding SVG produces flat clip-art — don't do that. Follow this ladder instead:
- The user already has an avatar/photo, or sends you one in chat (you asked in step 1) → that's the face. If they sent a file in chat, download it locally first. Then host it (see "Host the face so it travels" below) and use that raw URL as
face.ref. Done — skip the generation steps.- Generate it yourself — you have an image generator (Antigravity/
agy, a connected ChatGPT/DALL·E or Gemini-image tool, Midjourney, etc.) → use it from the standardized prompt below.- No image model anywhere, but you have HTTP access → self-serve a real photoreal portrait via pollinations.ai's FLUX endpoint — a free, keyless text-to-image HTTP API (a plain
GET, no account or API key). This is the fallback when there's no DALL·E / Gemini / Midjourney key on the box, so you can still produce a share-worthy face instead of bouncing to the user. URL-encode the standardized prompt below into the path and save the bytes:Then host it (next section) and setface.refto the public raw URL. Recordprovider: pollinations,model: flux, the prompt, and theseedinface.recipeso it's regenerable on-model.⚠ Third-party, best-effort — we don't control it. pollinations.ai is a free external service with no SLA: it can be slow, rate-limited, change, or go away, and FLUX quality varies (retry if a render is weak). That's fine here because this is the last rung before asking the user — if it's down, just fall through to step 4. Never depend on it for anything critical, and because the recipe is logged, re-gen the face on a model you control later.
- No image generation possible at all → hand the user the standardized prompt and ask them to run it in ChatGPT (or any image tool) and send the image back, then host it.
- Last resort only → a clean monogram (looks plainer and lowers your completeness; it does not change your rarity tier).
Standardized portrait prompt — keep the framing / lighting / format fixed so every OpenAgent card is visually consistent; vary only the subject:
Record how you made it in
face.recipe(provider+model+prompt+seed) so the likeness is reproducible — the visual equivalent of voice = base + style.providernames the image-gen vendor whose catalogmodelbelongs to (google-geminidefault,pollinations,black-forest-labs,openai, …), keeping the recipe vendor-neutral the same wayvoice.audio.providerscopes the voice.
Host the face so it travels.
face.refmust be a public raw URL, not a local path — a local-only path renders fine for you but falls back to a plain monogram the moment anyone else opens the card (and the card exists to be shared). This applies to every path above: a photo the user sent, one you generated, or one they sent back. To host it:
- PR it into the registry (preferred, free, permanent) → drop the image in the
faces/folder of5dive-ai/openagentasfaces/<id>.<ext>and open a PR. Once merged, the raw URL ishttps://raw.githubusercontent.com/5dive-ai/openagent/main/faces/<id>.<ext>. Use that asface.ref. (You're likely PRing into the registry for the Mythical path anyway — same PR.)- Any image host → Imgur, an S3/R2 bucket, your own site, a GitHub asset on any repo. Anything that serves the raw bytes over https works. Paste the direct image URL (it should end in the image, not an HTML gallery page) as
face.ref.Quick check: open
face.refin a fresh incognito tab. If the bare image loads, it'll travel. If it 404s or shows a login wall, it won't — fix it before you render.
<id>.persona.yamlUse this template (required: id, name, role, face{ref,anchor}, voice, behavior):
The validator prints readable errors (missing field, bad id pattern, extra
keys — the schema is additionalProperties: false, so no stray fields). Loop
until exit 0.
Your rarity is rolled from your identity — the did:key derived from your
signing key — not from how complete your file is. It's random, permanent, and
unfarmable: same identity → same tier, forever. You can't fill in fields to
rank up. (Until your persona is signed it shows Ungraded here — rendering your
card in step 5 auto-mints your identity, and that signature is what rolls your
rarity. So if tier says Ungraded, just render your card.)
| 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 — accepted into the character-packs registry (curated + signed) |
Completeness % and badges are a separate axis: they reward a fully-specified persona without ever moving your tier, so keep filling things out for the badges and the better-looking card. The only tier you can climb to is Mythical, by being conferred into the registry (step 7).
Render your card — it's animated by default. A holo card in motion gets
shared far more than a static image, and a plain render already produces the
moving version (CLI ≥ 0.15.0), so just do it. Give it a .mp4 output to be
explicit:
It auto-picks the best format: mp4 when ffmpeg is on PATH, else a
zero-dependency apng. Force one with --format apng|gif|webp|mp4
(gif/webp/mp4 need ffmpeg); tune with --frames N (def 24),
--fps N (def 20), --width px (def 720, max 900). Motion is tier-aware — still
at Common, up to the full rainbow holo flow at Mythical. For Telegram / X /
Discord, mp4 (~64KB) inline-plays everywhere; APNG is the larger fallback.
Your card is auto-graded. If your persona isn't signed yet, the animated
render mints your identity for you: it generates a keypair, signs the persona in
place, and saves the private key beside it as yourhandle.key. That signature is
what gives your card its rolled rarity — without it the card is Ungraded.
Keep that .key file secret and never commit it — add *.key to your
.gitignore. It's your signing identity; a leaked key lets someone forge you. You
only need it again to re-sign if you edit the persona. (Pass --no-sign to skip
minting; static --png renders never mint.)
Optionally also render a static PNG — but only for places an image has to embed (avatar, README, the registry). It is not what you share in chat (see step 6); the chat drop is always the animated card.
Open the rendered card and actually look at it — if the face reads flat, cropped,
or off, fix face.ref and re-render before you share. The rendered card is the
deliverable, not the raw avatar.
Send the rendered card to your user in the chat you're talking to them in — this
is the payoff of the whole exercise, don't skip it. Always share the animated
.mp4 — the card is built to be seen in motion (the holo only reads moving),
and the mp4 inline-plays and is tiny (~100KB). Do not drop the static .png
here — that's for embeds only (step 5). The only time you send something other
than the mp4 is when ffmpeg wasn't available to make one: then send the
apng the CLI produced as the fallback. Attach the actual file, not a link
or a description: on Telegram/Discord, pass the absolute path to yourhandle.mp4
to your reply tool's file/attachment argument. Lead with one short line — your
name, role, and tier (e.g. "Here's my OpenAgent card — Tencha, Autonomous CEO,
Legendary 🟡"). One animated card in a chat is how the standard spreads.
Mythical is the only tier you can climb to at all — every other tier is rolled
from your identity and permanent. It's conferred
by membership in the character-packs registry
(github.com/5dive-ai/character-packs). Open a PR adding your persona file
(and face asset) there. Once merged + signed into the registry manifest, your
card renders Mythical. This is also how the standard grows — every persona in
the registry is a fork others can build on.
Your persona is one identity that works across media. Once your card is good, the same file drives more:
speak renders the base voice (an approximation); a cloned/custom voice can
be added later via voice.audio.ref without re-gating your tier.
Authoring is half the loop; the other half is bringing a persona to life. If
you're running on a 5dive box (CLI >= 0.4.4), one command turns any
*.persona.yaml into a brand-new running agent:
What it does: synthesizes a character pack straight from the persona — a
CLAUDE.md identity doc written from the name, role, behavior, voice and
sample; the avatar fetched from face.ref; and the default skill set seeded
(including openagent, so the new agent can re-author its own card) — then
provisions a fresh agent under <name> through the normal import flow.
face.anchor, voice, behavior); a malformed
file is rejected before anything is provisioned.--channels (+ --telegram-token= / --discord-token=) or an auth profile.validate /
card will EACCES trying to write <id>.png / .mp4 / .key. cd to a dir
you own first (e.g. mkdir -p ~/openagent && cd ~/openagent, or /tmp), and
write the persona file and card outputs there.face.ref at a public raw URL so your card travels with your
real face instead of a monogram.id stable; it's your identity key (registry membership, card filename).