OptionalassistantOptionalenabledOptionalhistoryIndex into history below which the rolling window may trim, and at or above which it may not. Protects a task that must survive intact from an agent whose window is deliberately short.
Deliberately not in AgentConfig and never saved. maxHistoryMessages is
operator configuration; this is transient state about the task in flight, and
persisting it would leave an agent looking as though its window had been
changed by hand. A restart clears it, costing at most the protection on one
task in progress.
It also needs no clearing. Re-pinning ends the previous pin, so an abandoned task is reclaimed the next time one starts, and the worst a stale pin can do is keep more history than intended — never drop any.
OptionalidOptionalmaxOptionalopenaiOptionalownerOptionalpackThe pack this agent is filed under. See AgentConfig.pack.
OptionalpackThe pack template's key, when this agent came from one.
Private, agent-specific context that is visible only to this agent — never to other agents. Injected into the agent's transient (uncached) prompt message rather than the cached system instructions, so it can change frequently without invalidating the prompt cache. In stories this holds the character's inventory and conditions; contrast with description, which is the public appearance every other agent can see.
OptionalsmallOptionaltemplateThis agent intends to send MODERATE messages, so its room needs a moderator to route them.
For a human-controlled agent it is also what removes the action and target pickers from the room's composer: the player types, the room forces the message to MODERATE, and the moderator decides who hears it and who answers.
For an AI agent it is a declaration, not a coercion. An agent emits MODERATE
by its own choice — either its perceive schema offers moderate as a way to
defer the routing decision, or it has no schema at all and answers in prose,
which Room.parseAgentResponse converts. An agent that names its own targets
keeps doing so.
OptionalvectorAttaches an artifact to the agent
The artifact ID
Replace this agent's conversation history with a single summary message.
Uses the compact_agent prompt, resolved via the standard lookup order:
user/
Drops the newest message from history.
From the end only, which is what makes it safe to call repeatedly: the head of history is untouched, so a provider that requires the conversation to open on a user message still gets one. It can leave two messages of the same role adjacent, which the APIs accept and fold into a single turn.
The caller decides what a message is worth — nothing here asks whether the message being removed is an agent's answer or the prompt that drew it, because a person undoing a turn wants both gone and clicks twice.
True when a message was removed, false when only framing was left
Detaches an artifact from the agent
The artifact ID
OptionalimageProperties: Record<string, any>OptionalreferenceImageArtifactIds: string[]Generates an image from a text prompt.
Text description of the image
OptionalimageProperties: Record<string, any>
Optional provider-specific image options
(e.g. width, height, quality) passed through to the underlying AI service
Promise resolving to { artifactId } on success or { error } on failure
Gets all attached artifact IDs
Array of artifact IDs
Gets formatted messages from the agent's history starting from a specific index
The index to start from (0-based)
Array of formatted messages
Gets the raw (unformatted) content of every message in the agent's history.
Array of message content strings
Whether this agent's own prompt folder supplies <name>.prompt, rather
than inheriting it from the shared roots. See
BaseAiService.hasOwnPromptFile for why both questions exist.
Whether <name>.prompt resolves for this agent, so a caller can tell an agent
that can run a kind of turn from one whose prompt folder has no prompt for it.
False when the agent has no AI service or no paths yet — the answer to "could this agent run that turn" is then no, which is what a caller wants to hear.
The size of this agent's conversation history in characters.
Total characters across every message in history
Whether this agent's history has grown past the compaction threshold.
An agent with maxHistoryMessages is excluded: a rolling window already
bounds it, and the two mechanisms answer different needs. A window is for an
agent whose old turns stop mattering — a moderator routing the next message
does not need last hour's. Compaction is for one whose past must survive in
some form, which is why it costs a model call to write a summary rather than
dropping messages off the front.
True when compaction is worth a call
Notifies listeners that the agent state has changed Triggers SSE updates if callback is registered
Marks the current end of history as the start of a task the rolling window must not trim into.
A no-op for an agent with no window: there is nothing to protect it from, and a pin on an agent that keeps everything would only be a field to explain. That is what makes it safe to call from a shared path — the Dungeon Master running its own fight keeps its whole campaign either way.
Call it before the message that starts the task is added to history, so the task's own opening instruction is inside the pin rather than the first thing dropped.
Saves the agent to disk via AgentStoreService Called automatically after conversation history changes
Sets the callback to be called when agent state changes Used for SSE updates to push changes to connected clients
Function to call when state changes
Trims conversation history to keep only the last N messages if maxHistoryMessages is set Preserves system messages (role: 'developer') at the start of history Used for rolling window history management (e.g., moderator agents)
A historyPin raises the floor: everything since the pin is kept even when that is more than the window allows. The window still applies to whatever came before it, so a specialist handed a second task drops the first.
Allow history to grow 'threshold' messages past the limit before trimming a 'threshold'-sized chunk of messages at once
StaticcompactionHow large a history may grow, in characters, before it is worth compacting.
Read per call rather than cached so an operator can retune a long-running server without restarting it. Characters rather than tokens because it is the one measure available without asking a tokenizer, and the threshold only has to be roughly right — four characters to a token is close enough to make 100,000 mean "about 25k tokens".
The threshold in characters
StaticgenerateGenerates a nickname from an agent name by taking the first word
The full agent name
The first word as nickname, or the full name if empty
The packs the owning user has enabled, consulted only when promptFolder is a bare name — a pack-qualified one always resolves.
A thunk rather than an array because an agent outlives a toggle: the user can enable a pack while this instance is cached, and a snapshot taken at construction would need invalidating across every cached agent, room and service. Reading through the thunk means there is nothing to invalidate.
Absent means "scan no packs", which is exactly the behaviour from before packs existed. Deliberately not in
AgentConfig— it belongs to the user, not the agent, and persisting it would freeze a copy of the enabled set.