Skip to main content

ai-identicon

Generative, animated avatars for AI agents — a deterministic visual identity grown from a seed string. Instead of a photoreal face (creepy) or a cartoon mascot (cheesy), each agent gets an irregular faceted presence: a "broken-whole" cluster of crystalline shards that reads as an object with character, and can come alive — listening, thinking, speaking — without ever pretending to be human.

Same seed → same avatar, forever, under a given generation version.

A presence orb idling — breathing, glowing, gently turning

The ai-identicon gallery — a live "presence orb" at idle, with the full genome and personality controls

from ai_identicon import Genome, color_svg, line_art_svg

g = Genome.from_seed("agent://alice")          # deterministic identity
open("alice.svg", "w").write(color_svg(g))     # a filled, shaded portrait
open("alice-line.svg", "w").write(line_art_svg(g, "white"))  # line-art, for dark UIs

Why

  • Deterministic & frozen. Every avatar is derived from (seed, algo_version, brand, overrides). The generation algorithm is versioned and immutable: improving it later ships as a new ALGO_VERSION, so an existing agent's face never changes under it. A committed golden-file suite locks each version.
  • Identicon-grade distinctness. Curated, perceptually-spaced hue buckets and categorical materials (the lesson from jazzicons/blockies) so two seeds are either clearly the same or clearly different — not a subtle blur.
  • Alive, but calm. A headless state model (idle / listening / thinking / speaking / streaming / notify / success / error) with gaze choreography, breathing, blinks, and shard micro-physics. Present without being noisy; never interrupts.
  • Zero-dependency core. genome, geometry, model, portrait, controller are pure Python. SVG portraits need nothing. The live animated widget and mic-reactive audio are an optional Qt extra.

The states

The orb expresses what an agent is doing through motion and light — never a face. One seed (bmev5p5akc), all eight states:


idle
at rest, breathing; the odd blink

listening
turns to face you; ripples drift inward

thinking
comes apart to turn it over, gaze down‑right

speaking
voice drawn as a waveform around it

streaming
text arriving; a bright point laps its edge

notify
a chirp and an excited spin; self‑returns

success
a warm pulse and spin‑up; self‑returns

error
seized: rotation frozen, flushed red, one flinch

speaking is voice, streaming is text tokens landing — the two output channels. notify / success / error are transient: they play out and settle back to idle on their own.

Install

pip install ai-identicon          # core: genomes + SVG portraits (no deps)
pip install "ai-identicon[qt]"    # + the live animated widget and audio

Static portraits (pure, no Qt)

from ai_identicon import Genome, color_svg, line_art_svg, export_svg

g = Genome.from_seed("EK7f...aid-prefix")
color_svg(g, px=40)               # tuned for a 40px avatar
line_art_svg(g, "black", px=40)   # dark strokes for light UIs
line_art_svg(g, "white")          # light strokes for dark UIs
export_svg(g, "out.svg", variant="color")

Portraits render the canonical front pose (physics-settled), size-aware: at small sizes strokes thicken and near-coplanar interior lines fade to whispers, so the mark still reads as a shape at 40px.

Live widget (Qt)

from ai_identicon import Genome, AvatarController
from ai_identicon.widget import PresenceWidget
from ai_identicon.audio import SoundBank

orb = PresenceWidget(Genome.from_seed("agent://alice"), sounds=SoundBank())
ctl = AvatarController(orb)       # map your assistant's lifecycle to states
ctl.thinking(); ctl.speaking(); ctl.on_audio(amplitude=level)

Run the interactive gallery — installed as a command, no clone needed:

pip install "ai-identicon[qt]"
ai-identicon-gallery              # optionally: ai-identicon-gallery <seed>

Or try it without installing anything: pipx run --spec "ai-identicon[qt]" ai-identicon-gallery. Its copy 📋 button puts the avatar on the clipboard to paste into chats/notes.

Copy to clipboard (Qt)

from ai_identicon import Genome
from ai_identicon.clipboard import copy_to_clipboard   # needs a running Qt app

copy_to_clipboard(Genome.from_seed("agent://alice"))   # pasteable PNG

Copies a PNG (with the SVG attached as a bonus MIME) — PNG is the format that pastes reliably into Obsidian, MS Teams, Signal, Discord, Slack, and docs, and it keeps transparency so the avatar drops onto any background. The live widget has a convenience method too: presence_widget.copy_to_clipboard().

Customization & brands

from ai_identicon import Genome, Brand

# pin specific fields; everything unpinned still tracks the seed
g = Genome.from_seed("alice").with_overrides(material=1, hue=250)

# constrain a whole product's palette/materials to a brand
brand = Brand(hues=(215, 250, 285), materials=("crystal", "glass"))
g = Genome.from_seed("alice", brand=brand)

g.to_dict()   # {seed, algo_version, brand, overrides} — the portable identity

Determinism contract

The package version (semver) and ALGO_VERSION (the avatar-generation contract) are independent. Package releases never alter an existing seed's avatar; only a new ALGO_VERSION may, and prior versions stay renderable. This is enforced by tests/golden_v1.json.

Security note

An avatar is an identity affordance, not a control. A determined party can grind seeds toward a look-alike, so never let the avatar substitute for a verifiable identifier (e.g. show the full AID/prefix where trust matters).

Meet some of the faces

Sixteen names, sixteen seeds, sixteen agents you'd know on sight — each one idling below: breathing, glowing, gently turning. All just Genome.from_seed(name), deterministic, so "James" always looks like James, everywhere, forever. 👋


James

Mary

Michael

Jennifer

William

Elizabeth

David

Sarah

John

Jessica

Robert

Emily

Joseph

Emma

Daniel

Olivia

License

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ai_identicon-0.8.1.tar.gz (7.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ai_identicon-0.8.1-py3-none-any.whl (48.5 kB view details)

Uploaded Python 3

File details

Details for the file ai_identicon-0.8.1.tar.gz.

File metadata

  • Download URL: ai_identicon-0.8.1.tar.gz
  • Upload date:
  • Size: 7.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ai_identicon-0.8.1.tar.gz
Algorithm Hash digest
SHA256 6fd42f3af437fd51a2c687d8403fa38d6619d8582f4a886e206e55cd6fe4ecb7
MD5 974313c1a3489e7b5f278865387d171e
BLAKE2b-256 f3fdf9f1b06bf0926936e20624ee21bf36ed2de84b258021b54ca75571a73de5

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_identicon-0.8.1.tar.gz:

Publisher: publish.yml on seriouscoderone/ai-identicon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ai_identicon-0.8.1-py3-none-any.whl.

File metadata

  • Download URL: ai_identicon-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 48.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ai_identicon-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c650ce5a2dae017047458c7166fb47f82badb3120e31b5f51c33cda824ac45bb
MD5 1f98fc7064f222c44b13fb863a705eb9
BLAKE2b-256 174f0a19e8432ecde37f71f7731be92679cacbde055a55b88509d59316dc3dc0

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_identicon-0.8.1-py3-none-any.whl:

Publisher: publish.yml on seriouscoderone/ai-identicon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page