The Workspace server has exactly one tool. It takes a Workspace document URL, a Charm selector (agentName or agentId), and an optional message — and returns the Charm's reply. The Charm answers using everything in the document above the insertion point as its context.This is the surface for "given everything I already wrote in this Workspace, please respond here." Not a chat thread, not an autonomous task — a single, contextual turn.Endpoint: https://api.charmiq.ai/mcp/workspaceFor Developers — Workspace is routable but currently not advertised by the root discovery endpoint (list_servers). Call its URL directly; don't expect it to appear in dynamic discovery yet.
The One Tool
| Tool | What It Does |
|---|
prompt | Run one selected Charm inside a Workspace document and return its reply |
The call shape: prompt(uri, agentName | agentId, as?, message?, referenceMaterial?).| Argument | Meaning |
|---|
uri | The Workspace document — either charmiq://workspace/{id}[#fragment] or `https://(team |
agentName | Name of the Charm to run. Provide exactly one of agentName or agentId |
agentId | Stable identifier of the Charm to run. Provide exactly one of agentName or agentId |
as | (Optional) The persona to attribute the caller turn to in the document |
message | (Optional) Caller message. Omit it to run the Charm directly on the document context |
referenceMaterial | (Optional) Extra Reference Material for this one call — see below |
The user copies the document URL from their browser. Your application passes it directly — the browser form is accepted alongside the charmiq:// form.Where the Question Lands
The #fragment portion of the URL — if present — determines where the question is inserted:| URL Shape | Behavior |
|---|
URL with no #fragment | Question and reply appended to the end of the document |
URL with #fragment resolving to a known anchor | Question and reply inserted at that point |
URL with #fragment that does not resolve | Falls back to appending. Response carries anchorResolved: false |
Inserting mid-document is how the user has the conversation embedded where they're already working, rather than at the bottom.The Charm Sees the Document, Not Your Prompt
This is the key thing to understand: the Charm's context is the document content above the insert point, not the conversation history you've sent through MCP. Each call to prompt is independent — the Charm re-reads the document every time. Prior questions and replies that landed in the document are visible naturally, because they're in the document above where you're inserting now.Your application doesn't accumulate state. You see the Charm's reply; the document accumulates the conversation as a side effect.Per-Run Reference Material
A Workspace has a saved set of Reference Material — the documents, assets and folders the Charm considers — managed with the Context server (add_context / update_context / remove_context).prompt's referenceMaterial argument adds material for a single call. Each entry is a charmiq:// URI plus optional routing:referenceMaterial: [
{ uri: "charmiq://workspace/dennis-memory" }, // the model reads it (default)
{ uri: "charmiq://file/sales-2025.csv", sendToSandbox: true } // the Charm's code runs against it
]
It's merged onto the document's saved set (de-duped) and not persisted — one call, no toggle to undo. A per-call entry is additive and takes precedence: it's included even if that same document is disabled in the saved context. A bare entry defaults to the model reading it; set readByModel: false to hide it from the model, or sendToSandbox: true to give its raw bytes to the code-execution sandbox. Use it whenever material is specific to one run; use the persistent context for material that should stay loaded across runs.For multi-agent orchestration where each call needs different context, pass that context per call with referenceMaterial and keep the saved context for the shared, always-on set.Reference Material attached to a Charm does not travel. A Charm is itself a document, and a User can attach Reference Material to it — but that's authoring context for editing the Charm, symmetric to attaching context to a Workspace. It is not carried along when the Charm runs here; a run resolves Reference Material from the document it runs in plus whatever referenceMaterial you pass.
A Typical Sequence
- User shares a Workspace URL with your application.
- You call
prompt(url, "Editor", "User", "What's the main argument?") — answer comes back, and a Q+A block lands at the end of the document. - User reads the reply, asks a follow-up.
- You call
prompt(url, "Editor", "User", "And what does it miss?") — the Charm re-reads the document (including the previous Q+A) and answers the follow-up.
No conversation IDs, no session tokens. The document is the state.Orchestrating a Panel of Charms
prompt looks like Q&A, but its real power is directing several independent Charms against one shared document. The document is the shared reality; each call drops one Charm into it with exactly the context you hand that Charm, and you control the order. Saved context is the always-on set every Charm shares; referenceMaterial is the per-call spotlight — this Charm's memory for this turn.Worked example: a persona panel
Suppose you're testing launch copy and want to see how real customer segments react. Build them:- One Charm per segment — not "a skeptical buyer" but "Dana, a budget-conscious ops manager burned by two SaaS migrations who reads every renewal clause." Specific personas produce specific reactions. (Agent server:
create_agent.) - One Workspace per persona, holding their situation — budget, prior tools, current pain. That's their memory, kept separate from their personality (which lives in the Charm's System Prompt).
- A review document with the draft copy at the top and a
## Reactions heading. Attach the shared, neutral material — the brief, the product facts — as saved context once.
Then run the panel — each persona's memory rides in on the call that summons them:# sharedBrief is already saved context on reviewDoc — shared by every persona
for persona in [Dana, EnterpriseBuyer, StartupFounder]:
prompt(
uri = reviewDoc,
agentName = persona.name, # or agentId = persona.agentId
referenceMaterial = [ { uri: persona.memoryDoc } ], # this persona's memory, this call only
# no message — the copy and the reactions already in the document ARE the prompt
)
Each persona reads the same copy and the reactions stacking above them, then responds in character — Dana flags the renewal clause, the enterprise buyer asks about SSO, the founder skims and bounces. You didn't write those reactions; you convened them, with one self-describing call per voice and no context to set up and tear down between them.Keep each persona in its lane
Two lines in every persona's System Prompt (set once, applied to every call) keep a panel from collapsing into one Charm narrating everyone:You are a respondent, not a scriptwriter. Answer ONLY as yourself;
never write another persona's words or thoughts. Stop when your point is made.
You ARE this persona, not a narrator describing them. Speak in the first person.
Without the first, one persona will script the whole panel in a single reply. Without the second, you get detached play-by-play ("She'd probably find this concerning") instead of a voice ("This renewal clause is a dealbreaker").Don't summarize the document back to the Charm. Re-stating "the last persona said X, now react to X" in every message pays tokens to tell a Charm what it can already read above its insertion point. Call the persona, pass its memory, and let it read the room.
Where each piece of material goes
Run this in your head: same material on every call → saved context; different per Charm or per turn → referenceMaterial. If you catch yourself passing the same URI on every call, promote it to saved context and stop repeating it.Patterns
- Provide exactly one of
agentName or agentId. No default Charm. If the user's instructions don't specify which Charm to run, ask them. - Anchors are best-effort. Check
anchorResolved in the response — fall back gracefully if the document was edited and the anchor no longer exists. - Prefer mid-document insertion when the user gave you a fragment. That's almost always what they meant. Appending to the end is the fallback, not the default.
- Each call is fresh. Don't try to keep a "conversation token." The document is the durable history.
- Per-call material goes in
referenceMaterial. Merged onto the saved context, not persisted. Use add_context only for material that stays loaded across runs. - Personas are Charms; situations are Workspaces. Durable personality → System Prompt. Swappable facts →
referenceMaterial. One persona re-points at ten scenarios. - Direct by sequencing, not narrating. You decide who speaks next and what they can see; let the document carry what was said.
- The pattern isn't just marketing. Code-review personas, stakeholder sign-off, red-team/blue-team debates, user-research synthesis — anywhere "how would these specific people react to this?" is the question.
Next Steps
→ Chat MCP Server — When you want a dedicated Chat document for a multi-turn conversation instead of injecting into a Workspace.→ VFS MCP Server — Read or edit Workspace documents directly.→ Agent MCP Server — Discover the Charms whose names you'll pass into prompt.