What the model is told
Every request that asks the model to go on with the conversation carries two kinds of text besides it: instructions, which say how to work, and facts, which say what is true of the session right now. They travel separately, and only the facts that changed are sent again. The request for notes a compaction makes carries neither.
Instructions
The instructions are crucible's own, in the tone you chose: how to hold a task,
read before changing and say where the work stands. Three
systemPrompt keys shape
them: tone picks that tone, append adds to them and custom puts your own
in their place. They are fixed when crucible starts and go in the provider's
system field. Nothing about the session enters them, so a new model, a new tool
or the date rolling over never rewrites them.
Facts
The facts come in six sections, sent in this order:
| Section | What it says |
|---|---|
| Where you are working | The workspace root every tool path is relative to. |
| Skills you can open | The skills that can be opened. Crucible does not look for skills, so this says none were discovered. |
| Environment | The UTC date, the operating system and the processor architecture. |
| What is answering | The model's name and the effort it was asked at, or that the vendor's default applies. |
| What you have | The names of the tools advertised for this request. What each does travels in its own schema. |
| Permissions | The permission mode and the scopes you allowed for the rest of this session. |
The permissions section reports; it does not authorize. It ends by saying so, and a call is still checked by the permission engine as if the section were not there. Your rules are not in it. Each section is bounded: at most 64 skills and 64 allowed scopes are named, each cut to 200 characters, and the rest are counted.
Each section is sent as a user-role message of its own, not in the system field, and stays in the conversation like anything else that was said. They are first sent with your first prompt, so the first request reads your question, then the six sections.
Only what changed
crucible keeps what it last told the model, section by section, and compares before every request, including each one inside a turn:
- Nothing changed: nothing is sent.
- A section changed: only that section is sent, and it says what changed:
## Model changedwith the new model and effort after/model, or## What you have changedwith the tools added and removed. - The model has never been told: the whole section is sent. That is every section at the start of a session.
The first turn of a session sends the six sections once, however many tool
calls it makes, and a later turn under the same model, permissions, tools and
date sends none. Answering "Yes, and don't ask again this session"
partway through sends one short ## Permissions changed before the next
request, and the request after that sends none. A mode change made while a turn
runs is held for the next turn,
and is told to the model when that turn starts.
After compaction
A compaction replaces the middle of the conversation with a recap, and the facts that were said there go with it. So compaction removes every fact section, including any in the turns it keeps whole, and the next request restates all six in full. A change note that survived without the full statement it amended would leave the model knowing only half of it.
When a session is picked up
What the model was told is written to the session log as the words it was
sent, followed by a line recording the state behind them. --continue and
--resume read both back, so a resumed session carries on comparing against
what the model already knows rather than starting over. If nothing changed
while it was closed, nothing is restated. A section is sent only if it changed,
as when the date has moved on, you resume under another model or a tool was
added or removed. The tools are compared by name, so a run that builds the same
tools afresh does not tell the model about them again. The mode and any
session-long allow
are not carried over,
so the model is told when they differ from what it last heard.
The words are written before the state. If crucible stops between the two the first time a section is told, the next request finds words it has no recorded state for and restates that section whole, opening with a line that tells the model it supersedes every earlier version. A change told later whose state was never written is compared against the state recorded before it. A session written before crucible recorded that state is told all six in full.
Why it is split this way
A provider can reuse the start of a request it has seen before, and prompt caching depends on that start staying the same bytes. Instructions that never change come first; facts follow in the conversation, with the ones most likely to change mid-session last. Changing the model adds a short note at the end rather than rewriting the top.