Skip to content

Prompt & overrides

This page is the contract behind everything an avatar says: what it knows about itself, and who gets to change it.

The one rule

What you edit in the dashboard becomes the avatar’s default. What you pass as an API parameter is a per-session override that never persists.

Both write to the same fields — system prompt, backstory, tools, config. They differ in durability, not in power:

Where it is writtenHow long it lastsVisible in the dashboard
Dashboard editA new profile rowUntil you change the default againYes, with history
POST …/profilesA new profile rowSame — this is the UI’s APIYes
Mint parameter (context.*, tools, config)NowhereOne sessionNo

An API caller can do either. POST …/profiles is the “make this the new default” call; the mint parameters below are the “just for this conversation” call. Reaching for the wrong one is the mistake this page exists to prevent.

How a prompt is assembled

Every session composes one system prompt on the GPU box, in this order:

[Core] Casola-owned safety and speech rules — always present, never overridable
<persona> the behaviour prompt ← system_prompt
[Backstory] who this character is ← backstory
[Tools] callable tool definitions ← tools
[Language] reply-language preference ← response_language

[Core] is owned by the box and ships with its code: reply length, no markdown, mirror the user’s language, safety rules. Nothing you send can weaken or replace it — which is what makes it safe to expose prompt editing to your own end users.

The resolution ladder

For each of system_prompt, backstory and tools, independently:

1. the session parameter (context.system_prompt / context.backstory / tools)
2. the profile (pinned via profile_id, else the avatar's default profile)
3. the sealed version (what the avatar was created with)

The first layer that has a value wins. Layers replace; they do not stack.

Resolution is per field. Overriding one field leaves the others resolving normally:

{ "avatar_id": "019…", "context": { "backstory": "A support specialist at Acme." } }

→ backstory from the session, system prompt from the profile, tools from the profile. Not “the session layer wins everything”.

Worked example

Given avatar Lyra:

Layersystem_promptbackstorytools
Sealed version (created by the wizard)“You are Lyra…""A former archivist…”
Default profile (edited in the UI)“You are Lyra, Acme’s guide.”lookup_order
Session parameters“Speaking with a returning customer.”

Resolved for this session:

FieldValuesource
system_prompt”You are Lyra, Acme’s guide.”profile
backstory”Speaking with a returning customer.”session
toolslookup_orderprofile

Note the backstory: the profile had none, so without the session parameter it would have fallen through to the version’s “A former archivist…”. Falling through is per field, and goes all the way down.

Replacing vs. adding

Two different jobs, two different parameter families. This is the second most common mistake after confusing defaults with overrides.

ParameterEffectCap
Replacecontext.system_promptDiscards the profile/version prompt entirely40,960
context.backstoryDiscards the profile/version backstory16,384
toolsDiscards stored tool config
Addextra_system_promptAppended after whatever won2,048
extra_backstoryAppended to the backstory block2,048
extra_toolsMerged into whatever tools resolved

If you want “the avatar as authored, plus one sentence about this caller”, you want the extras, not a replacement:

{
"avatar_id": "019…",
"extra_system_prompt": "The caller is Dana, a Pro customer since 2024. Their last ticket was about billing.",
"extra_backstory": "You and Dana have spoken twice before."
}

Restating the whole persona just to append a sentence is the anti-pattern extras exist to remove — it also costs first-turn latency (see Performance). Combined extras are capped at 3,072 characters because they ride inside the session token itself.

Use a replacement when the avatar genuinely plays a different role this session — the same face and voice hosting a different scripted scenario, for example.

Pinning a profile for one session

{ "avatar_id": "019…", "profile_id": "019fe4a0-…" }

Runs a non-default profile without changing anything stored — A/B testing a prompt, or a “chat with this version” affordance in your own UI. The profile must belong to the resolved avatar (400 profile_mismatch): asking for specific text and silently getting different text is precisely the failure profiles exist to remove.

Pinning the text with profile_id is orthogonal to pinning the assets with avatar_version_id — see Avatars. The two compose freely.

Knowing what actually ran

Every mint response echoes the text layer it resolved:

"profile": { "id": "019fe4c1-…", "hash_short": "a2271f20509d", "source": "default" }
sourceMeaning
paramYou pinned it with profile_id
defaultThe avatar’s default profile
noneNo profile — the sealed version’s own text ran

Log hash_short alongside your own session records and “which prompt was this user talking to?” stays answerable months later.

Credential fence

Every parameter on this page is secret-key only. A publishable, device or trusted-issuer credential sending any of them gets 403 tools_context_not_allowed (or 403 profile_pin_not_allowed for profile_id). context.memory_id is on the same fence, and so is erasing a memory store — whatever credential can create one can destroy it, and nothing weaker can do either.

That is deliberate: a publishable key ships to browsers where anyone can read it, and choosing which prompt runs is a server-side decision. Set overrides in your own backend, in the same place you decide which user gets which avatar.

Limits

FieldCap (characters)
context.system_prompt / profile system_prompt40,960 (~10k tokens)
context.backstory / profile backstory16,384
extra_system_prompt2,048
extra_backstory2,048
Combined extras3,072
context.history40 messages / 16,384 bytes
context.memory_ida UUID (see Avatar memory)
config (serialized)1,024 bytes

Caps are characters, not tokens (roughly 4 characters ≈ 1 token).

Exceeding a cap on a session parameter is a 400 — it is your input, so you should hear about it. Exceeding it on a stored profile clamps at mint with a server-side warning rather than failing the session, because stored data may have been authored by someone else at another time and a live call is the wrong place to discover it.

Performance

The composed prompt is re-sent to the language model on every turn. The [Core] block and the avatar’s own bundled persona are shared across sessions and stay warm in the model’s prefix cache; a session-level override breaks that sharing beyond [Core] for that session, so the first turn pays extra prefill proportional to prompt size. Later turns in the same session are cached.

  • Under ~3,000 characters: no perceptible effect.
  • Above that: expect the first reply to start slightly later. The dashboard’s prompt editor shows a size meter for this reason.
  • Prefer extra_system_prompt over restating the persona — it is small by construction and keeps the shared prefix intact.
  • Profiles — authoring the stored defaults, and the config catalog
  • Sessions — where these parameters are sent
  • Avatars — selecting which avatar, and which version