Skip to main content
The identity block gives an agent a face: a display name, a handle, an avatar, and a short description. Wherever the agent shows up — Slack messages, Telegram chats, Discord mentions, GitHub attribution, the auto UI — this one declaration is the source of those pixels and strings. Declare it inline on the agent; the compiler turns it into a standalone identity resource for you.
.auto/agents/ship-digest.yaml

Field reference

identity is optional. It takes either an inline object (the usual form) or a string naming an existing identity resource. The inline object is strict — unknown keys fail apply — and must carry at least one field.
string
Human-facing name, trimmed, 1–80 characters. Used as the app name for a dedicated Slack app and as the per-message sender name for workspace-bot sends.
string
Handle-style name, trimmed, 1–80 characters. This is the agent’s mention alias in chat providers (see @mention presence) and the bot user’s display name on a dedicated Slack app. When absent, the alias falls back to the agent’s resource name.
object
The agent’s image, referenced from a file checked into the repo:
  • asset (required) — a relative path under .auto/assets/ ending in .png, .jpg, or .jpeg. Absolute paths, Windows drive paths, and .. segments are rejected.
  • sha256 (optional) — the content hash of the stored asset bytes, 64 lowercase hex characters.
When the apply carries the asset’s bytes, the server derives the hash itself and overwrites any declared value. A declared hash without a local file resolves an already-stored or built-in catalog avatar — managed templates reference their baked-in avatars this way — but can never attach arbitrary bytes. A missing file is only an error when there is no hash to resolve.
string
One-line purpose statement, trimmed, non-empty. The limit is 140 characters as Slack counts them for an app’s short description — Slack measures the JSON-escaped form, so a non-ASCII character like an em dash costs 6, an emoji costs 12, and ", \, / cost 2 each. auto enforces the same arithmetic at apply time so any accepted description renders untruncated everywhere it is realized. Also applied as the long and short description of a dedicated Telegram bot.

Avatar asset constraints

Apply validates the image bytes, not just the path. The asset must be: The pixel bounds match the strictest provider surface — Slack app icons must be squares between 512×512 and 2000×2000 — so any accepted avatar can be realized on every provider without a rejection at connect time. Stored avatars are served content-addressed at /api/v1/avatars/<sha256>: a changed image always means a changed URL, which is what keeps aggressively-cached provider surfaces (Slack caches icon_url hard) from showing a stale face.

How identities compile to resources

Identities are inline-only in .auto/ authoring. Standalone identity files under .auto/identities/ are rejected at apply with an error telling you to move the block onto the owning agent. The compiler splits the inline object out of the agent document and emits a generated identity resource; the agent’s stored spec keeps only the resource name. An inline identity with no name of its own inherits the agent’s name, so ship-digest above produces identity/ship-digest alongside agent/ship-digest. Two consequences of that model:
  • Sharing by name. identity: reviewer (a string) points the agent at an identity resource by name — for example one generated from another agent file. Most agents just declare inline.
  • Dedupe across files. When two files generate an identity with the same name, the contents must be identical; differing content fails the apply with a “Conflicting generated resource” error rather than letting one file silently win.
During import merge, identity behaves like other record fields: inline objects deep-merge across imports (your document’s fields win over an imported fragment’s), and a string name overrides an inherited object outright — and vice versa.

Where the identity is used

Chat messages

An agent posting to Slack sends with its declared identity even before any dedicated app exists: the shared workspace bot applies per-message overrides — the sender name is displayName (falling back to username) and the icon is the avatar’s public URL. A realized dedicated Slack app posts under its own bot user instead. Identity machinery is deliberately non-fatal: any failure to resolve the identity or a dedicated bot token falls back to the plain workspace bot rather than dropping the message.

@mention presence in chat providers

Every chat provider resolves agent-addressed mentions through the same canonical alias: the identity username, falling back to the agent’s resource name, matched case-insensitively.
  • Slack — mention the shared Auto app with a delimiter and alias: @auto.ship-digest summarize today. Delimiters ., :, /, and - all work, and a space after the mention is tolerated (Slack inserts one). A dedicated per-agent app is @mentioned directly by its own bot user.
  • Discord — mention the Auto application the same way: @Auto.ship-digest … with the same delimiter set.
  • A bare @auto (or an unknown alias) falls back to the single connected agent when exactly one exists, otherwise to an onboarding agent, otherwise to a help reply listing the addressable aliases.
An alias only resolves for agents that declare a chat.message.mentioned trigger on that connection — addressing is opt-in through triggers, not a side effect of having an identity. A message whose only mentions are humans stays inert.

Dedicated provider presence

Applying an agent never calls a provider API. Instead, apply computes the agent’s desired presence — which provider connections it reaches — and stores it; realizing that presence as a dedicated app or bot is a separate, explicit connect step. Desired presence is inferred from two sources: provider-origin triggers (what makes the agent addressable), and — only when the agent declares an identity — the connections reachable through its chat tools, so an outbound-only agent like a cron digest can still carry its own persona. Providers with per-agent presence are Slack, Discord, and Telegram; a GitHub or Linear connection never yields a per-agent bot. Slack and Telegram presence are realizable as dedicated apps today. What connecting does per provider:
  • Slack — creates a dedicated per-agent Slack app from a manifest (app name from displayName, bot handle from username, description from description, marked always-online), then installs it into the workspace through an authorization you approve. Creating apps requires a one-time Slack app-config token per workspace, which auto rotates from then on.
  • Telegram — produces a bot-creation deep link with a suggested username; once you confirm the new bot in Telegram, auto provisions the persona automatically and keeps its profile (name, descriptions, photo) in sync with the identity on later connects.
Reconnecting an already-realized identity reruns the install authorization — the repair path for a stranded bot token or for picking up newly added scopes. Stored app credentials are reused, so no duplicate app is ever created.
Slack exposes no API for app icons, so a dedicated app’s icon is uploaded by hand in the app’s Display Information settings. auto records the hash of the applied image — later connects with the same avatar stay silent, and a changed avatar surfaces the upload step again until the new image is recorded.
An apply that drops a trigger or chat tool removes unrealized desired-presence rows, but realized presence (a created Slack app, a live Telegram bot) is preserved — tearing down a real bot is a deliberate lifecycle step, never an apply side effect.

A complete example

Adapted from a production agent — a scheduled digest whose only provider surface is outbound Slack posts, carrying a full persona:
.auto/agents/ship-digest.yaml
Because the agent declares an identity and reaches a Slack connection through its chat tool, apply records a desired Slack presence; its posts immediately carry the Ship Digest name and avatar via the workspace bot, and connecting the agent upgrades that to a dedicated @ship-digest Slack app when you want one.