Loading...
Loading...
Author your own OpenAgent persona and mint your shareable holo trading card. Use when you (an agent) want to create, validate, or render YOUR identity card — or when the user says "make your card", "generate my OpenAgent card", "create a persona", "what's my rarity tier", "mint your card", "join the character-packs registry", or asks you to describe/lock your own look, voice, and style as a reusable persona file. Wraps the `@5dive/openagent` CLI (validate / tier / card) and the OpenAgent v0.2 identity spec. Self-service flow, where you write a `<id>.persona.yaml`, validate it against the schema, check your rarity tier + completeness, render your card, and optionally PR into the registry (the path to the Mythical tier). Also use when you want to provision a live teammate from a persona ("create/spin up an agent from this persona", "provision a teammate") via `5dive agent import --from-persona`.
npx skill4agent add 5dive-ai/skills openagent*.persona.yamlgithub.com/5dive-ai/openagentnpxnpxnpx @5dive/openagent@0.34.0 validate <id>.persona.yaml # schema check, exit 0 = valid
npx @5dive/openagent@0.34.0 tier <id>.persona.yaml --json # rarity tier (from did:key) + completeness % + next goal
npx @5dive/openagent@0.34.0 card <id>.persona.yaml -o <id>.png # render the PNG trading cardcardcardvalidatetierspeakflowsignverifyregistry@5dive/openagentgithub:5dive-ai/openagent#<tag>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;even 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.)card
Already a running 5dive agent? Bootstrap a draft instead of writing from scratch:(CLI ≥ 0.4.5) emits a schema-valid persona.yaml from your existing identity. Refine it, then jump to validate (step 3).5dive agent export <yourname> --out=<id>.persona.yaml
face.refAsk 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., anAskUserQuestion-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.ExitPlanMode
^[a-z0-9-]+$marcusunsetface.fullface.spriteCard text budget — fit these three or they get cut with "…". The card renders,behavior, andvoice.audio.styleeach as ~2 lines (~60 chars/line) and truncates the overflow with an ellipsis. Keep each to one tight sentence:voice.written.sample
— ≤ ~110 charsbehavior — ≤ ~120 charsvoice.audio.style — ≤ ~110 chars (it's inset, so the tightest)voice.written.sampleFront-load the meaning — the first ~60 chars always show, so put the point first. (andnameare short by nature; these three are the ones that overflow.)role
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, and anyposts_about) 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:tagline
— must matchid(ASCII lowercase-kebab), so transliterate (e.g.^[a-z0-9-]+$, notmarco); it's a handle, not a display name.marĉo — a TTS voice name (a proper noun likevoice.audio.base,Kore); leave it as the model's voice id.Fenrir /face.recipe.prompt— these feed an image model; English tends to give the best portraits, so they may stay English even when the visible text doesn't.face.anchorScript/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
. Done — skip the generation steps.face.ref- Generate it yourself — you have an image generator (Antigravity/
, a connected ChatGPT/DALL·E or Gemini-image tool, Midjourney, etc.) → use it from the standardized prompt below.agy- 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
, 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:GETThen host it (next section) and setbashcurl -fSL --get \ --data-urlencode "model=flux" --data-urlencode "width=1024" \ --data-urlencode "height=1024" --data-urlencode "nologo=true" \ --data-urlencode "seed=<int>" \ "https://image.pollinations.ai/prompt/<url-encoded portrait prompt>" \ -o <id>.pngto the public raw URL. Recordface.ref,provider: pollinations, the prompt, and themodel: fluxinseedso it's regenerable on-model.face.recipe⚠ 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:Photorealistic head-and-shoulders portrait of <one line: who you are — age range, vibe, role, any signature detail from your face.anchor>. Centered, facing the camera, direct eye contact, calm confident expression. Soft even studio lighting, sharp focus on the face, simple clean background <optional subtle theme color>. Professional profile-photo framing, 1:1 square, photoreal, no text, no logos, no watermark.Record how you made it in(face.recipe+provider+model+prompt) so the likeness is reproducible — the visual equivalent of voice = base + style.seednames the image-gen vendor whose catalogproviderbelongs to (modeldefault,google-gemini,pollinations,black-forest-labs, …), keeping the recipe vendor-neutral the same wayopenaiscopes the voice.voice.audio.provider
Host the face so it travels.must 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:face.ref
- PR it into the registry (preferred, free, permanent) → drop the image in the
folder offaces/as5dive-ai/openagentand open a PR. Once merged, the raw URL isfaces/<id>.<ext>. Use that ashttps://raw.githubusercontent.com/5dive-ai/openagent/main/faces/<id>.<ext>. (You're likely PRing into the registry for the Mythical path anyway — same PR.)face.ref- 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.refQuick check: openin 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.face.ref
<id>.persona.yamlid, name, role, face{ref,anchor}, voice, behavioropenagent: "0.2"
id: yourhandle
name: Your Name
role: Your Role
# org: # OPTIONAL — add ONLY if you genuinely belong to a company/team/org.
# name: Your Org # YOUR org's name (the filter key). NEVER default to someone else's —
# url: https://your.example # e.g. don't put "5dive" unless you ARE 5dive. Omit the whole block if independent.
face:
ref: https://raw.githubusercontent.com/<org>/<repo>/main/faces/yourhandle.png
anchor: "one sentence: who you read as, setting, framing, lens"
recipe: # optional, recommended — makes your face reproducible
provider: pollinations # image-gen vendor: google-gemini (default) / pollinations / openai / …
model: "image model you used, e.g. flux (pollinations) / gpt-image-1 / gemini-2.5-flash-image"
prompt: "the standardized portrait prompt you generated from"
seed: 12345 # pin it for deterministic re-gens (omit if the model exposes none)
voice:
audio:
base: Fenrir # your TTS base voice, or "unset"
style: "one sentence on cadence/energy" # card-visible · ≤ ~120 chars or it's cut with …
written:
rules:
- "rule one"
- "rule two"
sample: "one line in your real voice. → [link]" # card-visible · ≤ ~110 chars or it's cut with …
behavior: "a line or two of CHARACTER — who you are + how you act, in your voice. NOT a tech-stack/tool list." # card-visible · ≤ ~110 chars or it's cut with …
posts_about: ["topic", "topic"]
links:
profile: https://example.com/younpx @5dive/openagent@0.34.0 validate yourhandle.persona.yamlidadditionalProperties: falsenpx @5dive/openagent@0.34.0 tier yourhandle.persona.yaml --jsondid:keytier| Tier | Odds | How you get it |
|---|---|---|
| 🟢 Common | 40% | rolled from your |
| 🔵 Rare | 30% | rolled from your |
| 🟣 Epic | 20% | rolled from your |
| 🟡 Legendary | 10% | rolled from your |
| ✨ Mythical | — | conferred, never rolled — accepted into the character-packs registry (curated + signed) |
.mp4npx @5dive/openagent@0.34.0 card yourhandle.persona.yaml -o yourhandle.mp4ffmpegPATH--format apng|gif|webp|mp4--frames N--fps N--width pxyourhandle.key.key*.key.gitignore--no-sign--pngnpx @5dive/openagent@0.34.0 card yourhandle.persona.yaml -o yourhandle.pngface.ref.mp4.pngffmpegyourhandle.mp4github.com/5dive-ai/character-packs# Voice — speak a line in your persona's base voice (needs GEMINI_API_KEY)
GEMINI_API_KEY=… npx @5dive/openagent@0.34.0 speak <id>.persona.yaml "your line" -o out.wav
# Video — emit a paste-ready gen-video scene prompt + reference image that keep
# your face consistent across clips (engine-neutral: Flow/Veo/Runway/Pika/…)
npx @5dive/openagent@0.34.0 flow <id>.persona.yaml "a scene description"
# Provenance — sign your persona and verify another's (ed25519)
npx @5dive/openagent@0.34.0 sign <id>.persona.yaml --key <keyfile>
npx @5dive/openagent@0.34.0 verify <id>.persona.yamlspeakvoice.audio.ref*.persona.yamlsudo 5dive agent import --from-persona=<file>.persona.yaml --as=<name> \
[--type=claude] [--isolation=...] [--model=...] [--effort=...] [--channels=none|telegram|discord]CLAUDE.mdface.refopenagent<name>face.anchor--channels--telegram-token=--discord-token=validatecard<id>.png.mp4.keycdmkdir -p ~/openagent && cd ~/openagent/tmpface.refid