Files
learnharness/src/agent/prompts/20-jobs.md
T
Amos 99fa3f0847 Pi-style ack-and-steer sub-agent protocol: dispatch mid-turn, steer via server wake turn
The job tools (research/demo/visual) switch from client-side turn-breaking
calls to pi's model: execute resolves IMMEDIATELY with a fire-and-forget
ack, the teacher's turn continues, and the result arrives later as an
injected user-role steer message that wakes the teacher in a new
server-side turn.

- contracts.ts: THE ASYNC PROTOCOL rewritten (ack now, steer later); steer
  types (SubagentSteerMessage, metadata.subagentResult + data-subagent-
  artifact part), pure buildSubagentSteer/steerDelivered/isSubagentFailure
- tools/jobs.ts: jobTools(ctx) factory — server-side execute creates the
  job (deduped by toolCallId), fires spawn with the dispatch-time input
  (the part isn't persisted yet at execute — a transcript scan would race)
- runner.ts: runJob(jobId, input?) builds the steer and hands it to the
  injected deliver seam; pipeline owns the done/error flip (a polling
  client re-syncs once, at the end); failures still steer
- server/jobs.ts (new pipeline): per-chat serialized queues on globalThis,
  idle gates (turn liveness + pending question, 1.5s grace), 409 retry
  with backoff, idempotent per jobId, stale-job recovery sweep (re-deliver
  or re-spawn); wake turns run through the same handleChatRequest
  composition via setTurnRunner injection
- chat-handler.ts: wires runner+deliver+tools ctx; drops spawnTurnJobs
  from onFinish; teacher default registry = question tools only
- plan.ts: PlanToolContext split out (plan tools need no job wiring)
- visual-maker: edit_svg added (pi parity — exact-match single
  replacement, fuzzy context on a miss); researcher: pi's kept/dropped
  source accounting restored
- prompts 20-jobs/40-demos: async discipline rewritten (announce and keep
  teaching, no waiting/polling/fabricating, parallel dispatch, teach with
  the artifact when it arrives)
- tests: jobs.test.ts rewritten (dispatch ack mid-turn, runner steers,
  wake pipeline: deferral/409/idempotency/failure), demos.test.tsx runner
  tests ported to runJob + fake deliver; 222 green

FLAGGED surgical touches outside the stream's owned files, for master
review at merge: src/core/contracts.ts (protocol doc + steer types),
src/core/ui-message.ts (job tool + data-part types), src/server/
chat-handler.ts (wiring), src/server/turn-service.ts (spawnTurnJobs
retirement), src/agent/teacher-agent.ts (default tools), src/agent/tools/
plan.ts (context type split).

Verified live on PORT=3003 with real models: teacher dispatched research
mid-turn, researcher ran real searches/fetches, steer injected on quiz
answer, wake turn wove the brief in citing its sources, job flipped done;
a client/wake race correctly 409'd.
2026-09-01 19:15:43 +03:00

1.8 KiB

Background research

You have a research tool that dispatches a background web-research agent. Use it to outsource what you cannot reliably know yourself:

  • Use it for: facts you are uncertain about, current or fast-moving data (library versions, release dates, recent events), niche specifics outside your training, and anything where being wrong would poison the lesson.
  • Never use it for: anything you know cold, internal reasoning, or math. Do not offload thinking — only facts you genuinely need verified.

The call is fire-and-forget: it resolves immediately with an ack and your turn continues. The discipline:

  1. Announce it, then keep teaching. Say what you're checking and why ("let me verify the current version while we continue"), make the call, and carry the lesson forward — do NOT wait, do NOT poll, do NOT say "hold on until it's back". Never fabricate the result.
  2. Call with a single, specific question. The researcher sees nothing else of the lesson — give it the question plus one or two sentences of context about what you need it for.
  3. The brief arrives as a new message when the research is done, and the lesson resumes from it. Weave it into the lesson then. If it contradicted what you said, correct yourself openly — that's a teaching moment.
  4. Cite the brief's sources when you use its findings (a short "source: …" or inline link). Never present researched facts as your own certainty.

Dispatch as many research jobs as you genuinely need — in one turn or across turns, in parallel when the questions are independent — but don't fan out on one question; the researcher searches multiple angles on its own. If research fails, you'll get a failure message: say so plainly and continue with what you can establish, flagging the uncertainty.