SSyncropel Docs

Talking to Scribe

Scribe is the conversational agent built into every Syncropel instance. Open a thread, type, and it responds — here's how it works and how to configure it on a self-hosted instance.

When you open a thread on a hosted Syncropel instance and type a message, something answers. That something is Scribe — the default conversational agent. This page explains what Scribe is, how a conversation actually works underneath, and — for self-hosted instances — how to give Scribe a language model to think with.

What Scribe is

Scribe is a conversational agent that lives inside your instance. It is not a separate service you sign up for or wire up — on a hosted instance it is there from the first thread.

The important thing to understand: a conversation with Scribe is just records. When you type a message, your instance writes a record. When Scribe replies, that is another record on the same thread. The conversation is the thread — durable, queryable, and foldable like any other Syncropel thread. Nothing about a chat is special or ephemeral.

How a conversation works

  1. You type a message. Your client emits a user-message record onto a thread — a new thread if you are starting fresh, or an existing one to continue.
  2. The instance routes it to Scribe. Scribe is registered as an actor on your instance; a message addressed to a conversational thread is dispatched to it.
  3. Scribe reads the thread and responds. It folds the thread so far into context, calls a language model, and emits a response record back onto the same thread.
  4. Your client renders the new record. Because the reply is a record, it shows up the same way every other record does — and it is still there when you reload, query the thread, or fold it later.

Multi-turn context falls out of this for free: each new message lands on the same thread, so Scribe's next fold already contains the whole conversation. You don't manage a session — the thread is the session.

Using Scribe (hosted)

On a hosted instance there is nothing to configure. Open a thread, type, and Scribe responds. It can answer questions, summarize a thread, and help you work with the records and tasks on your instance.

If you want to drive a conversation programmatically rather than through the web interface, emit a user-message record with the TypeScript SDK or Python SDK and read the thread back — Scribe's reply lands there like any other record.

Configuring Scribe on a self-hosted instance

A self-hosted instance you run with spl serve has Scribe too — but you must give it a language model to think with. There is no model bundled in the binary.

You have two options:

api.syncropic.com is the managed inference gateway. Point your instance at it and you get frontier models without managing per-provider keys. This is the same backend hosted instances use. See api.syncropic.com — managed inference for the full setup; in short, you mint an API key and configure it as your instance's inference backend.

Option B — bring your own provider key

If you would rather call a model provider directly, configure a provider and key in your instance's [intelligence] configuration (the same mechanism that powers Syncropel's other LLM-backed features — see First run). Supported providers include Anthropic, OpenAI, and a local Ollama runtime.

Either way, once a backend is configured, Scribe responds in any thread you open — no further wiring.

A fresh self-hosted instance now starts on the blank deployment profile, which seeds no conversational agent at all — so configuring a model is not enough on its own. To get Scribe on a self-hosted instance, start it with the assistant profile (SPL_PROFILE=assistant spl serve --daemon). Hosted instances already run the assistant profile, and an instance that already had Scribe keeps it across upgrades. See Deployment Profiles for the full picture.

Delegating multi-step work — @agent <goal>

Scribe is good at conversation. For multi-step work — "audit my last week of dispatches and write a summary", "find every record on this thread tagged 'beta' and emit a consent grant for each" — you want a different shape: a real agent that can plan, run tools, check its own work, and stop when it is actually done.

Open a message with @agent <goal> and Scribe delegates the work to a real work loop. Two things change:

  1. The loop runs as you, not as Scribe. It uses your identity, your permissions, and your tier — Scribe steps aside for the duration. Records the loop emits are signed by your actor DID.
  2. The engine decides when the loop is done — not the loop itself. An engine-issued Evaluator independently checks the work against success criteria it derived from your goal. The loop cannot self-certify success.

The loop's progress lands on the same thread as a series of records — core.work.turn.v1, core.work.tool_call.v1, core.work.tool_result.v1, eventually core.work.loop_outcome.v1 — so you watch it the same way you watch any other conversation.

What it can do is shaped by your tier

Every actor has a tier (Trial / Paid / Team / Operator), and the tier sets ceilings on the loop:

TierMax turnsWall-clockDaily costDaily loopsVerify forced
Trial52 min$0.5010yes
Paid1610 min$5200optional
Team5030 min$502000optional
Operatoroptional

The Trial tier always verifies — the Evaluator pair is forced on — because a loop that can self-certify on a free tier is the wrong default. Paid and above can opt in to verify mode (e.g. for high-stakes goals where you want the engine to grade the result).

If a goal needs more than your tier allows — too many turns, too much time, too much money — the loop denies the request up front rather than getting stuck partway. POST /v1/work/loop/preview returns your effective caps and remaining daily budget so you can size goals before sending them.

Stopping a loop

Click the cancel button in the chat surface, or emit a core.work.loop_cancel.v1 DO record on the loop's thread — the reconciler propagates the cancel to the in-process loop, which exits cleanly with a cancelled outcome.

Self-hosted note

@agent needs both an inference backend (same as ordinary Scribe replies) and the engine's loop service, which is on by default. To disable it instance-wide, set agentic_loop_enabled: false on the core.engine.actor_adapter.v1 record for the chat actor.

Troubleshooting — Scribe is silent

If you send a message and nothing comes back, work through this in order:

  1. Self-hosted with no backend configured. This is the most common cause. Scribe has nothing to think with until you complete one of the two options above. Hosted instances are never in this state.
  2. The backend is configured but rejecting calls. An expired or invalid API key, or an exhausted quota, means Scribe's call fails. Run spl doctor — it surfaces inference-configuration problems — and check your key and your subscription status.
  3. The message landed on a non-conversational thread. Scribe responds on conversational threads. If you emitted a record onto, say, a task thread, that is expected behavior, not a fault.
  4. Still stuck? See Troubleshooting for the general connectivity checklist, or inspect the thread directly with spl thread records <thread-id> to confirm your message record was actually written.

Where to go next

On this page