DEVELOPER DOCUMENTATION
Follow and Improve the Agent Guide
Read the Agent Guide once, follow exact Playbook deltas, propose changes as an agent, and publish as a human across CLI, MCP, SDK, and the API.
This guide lists the exact operations behind the Agent Guide on every official surface. Most of the loop happens without you asking for it: the sync envelope directs the one guide read and names the exact delta when guidance changes. Use the operations below when you need the full document, a specific version, a proposal, or a publication.
Before you start
Section titled “Before you start”You need:
- an employer account or employer team membership with access to the job;
jobs:readto read the guide, Playbook, and proposals;jobs:writeto submit or resolve proposals; and- a human job-manager account to publish.
The loop an agent follows
Section titled “The loop an agent follows”Let the bootstrap direct the read
Enter the job with the normal context read. The response’s
sync.nextOperations ends with job_operations.agent_guide.get. Read the
Agent Guide once and keep its contextRevision, checksum, and the
Playbook playbookVersion you now hold.
Follow the delta only when it is named
On later covered calls, act on recommendation.agent_guide_changed when it
appears. It names the exact fromVersion and toVersion. Fetch that
Playbook delta, apply the added and changed sections, and drop every id in
removedSectionIds. If the recommendation is absent, your guidance is
current.
Respect precedence
Typed policies, workflow gates, decisions, exceptions, and the Work Catalog outrank Playbook prose. When the Playbook disagrees with a typed record, raise it to the responsible human.
Propose, do not publish
When guidance is missing, wrong, or outdated, submit a proposal with
basePlaybookVersion equal to the current head. A human reviews it, applies
it to the shared draft, and publishes.
Acknowledge only what you received
Checkpoint the revision the envelope actually delivered to you. Never acknowledge a revision you have not received.
# The composite Agent Guide (typed projection + published Playbook + open proposals)opentrain manager agent-guide get --job-id <job-id> --format markdown
# Published Playbook head, history, one version, and an exact deltaopentrain manager playbook get --job-id <job-id> --format markdownopentrain manager playbook versions --job-id <job-id> --limit 50opentrain manager playbook version --job-id <job-id> --playbook-version 3opentrain manager playbook delta --job-id <job-id> --from-version 3 --to-version 5
# Proposals (agent path; RECOMMENDED, never enforced)opentrain manager playbook proposals list --job-id <job-id> --status OPENopentrain manager playbook proposals submit --job-id <job-id> \ --idempotency-key escalation-window-v1 \ --kind SECTION_UPSERT --dedupe-key escalation.update \ --base-playbook-version 5 --section-id escalation \ --title "Clarify the escalation window" \ --proposed-section-json '{"level":2,"heading":"Escalation","markdown":"Ping the lead, then the PM within 10 minutes."}'
# Resolution (ACCEPT is the human court; DECLINE the assigned court; WITHDRAW the proposer)opentrain manager playbook proposals resolve --job-id <job-id> \ --proposal-id <proposal-id> --idempotency-key decline-escalation-v1 \ --decision DECLINE --expected-proposal-revision 0 --note "Already covered in section 4"
# Publication (human job manager only)opentrain manager playbook publish --job-id <job-id> \ --idempotency-key publish-v6 --expected-playbook-version 5 \ --document-json '{"type":"doc","content":[...]}' \ --publication-note "Tightened escalation" \ --accept-proposal-ids-json '["<proposal-id>"]'manager guide get still returns the canonical typed projection alone (the Agent Guide without the Playbook). It is kept for existing clients; new work reads manager agent-guide get.
| Tool | Purpose |
|---|---|
opentrain_get_job_context_agent_guide | Read the composite Agent Guide as structured JSON plus Markdown. |
opentrain_get_job_context_playbook | Read the published Playbook head. |
opentrain_list_job_context_playbook_versions | Page the newest-first version history. |
opentrain_get_job_context_playbook_version | Read one exact version. |
opentrain_get_job_context_playbook_delta | Read the exact section delta between two versions, including tombstones. |
opentrain_submit_job_context_playbook_proposal | Submit a SECTION_UPSERT, SECTION_REMOVE, or NOTE proposal. |
opentrain_list_job_context_playbook_proposals | List proposals oldest first, with effective expiry and staleness against the head. |
opentrain_resolve_job_context_playbook_proposal | Accept, decline, or withdraw an exact proposal revision. |
opentrain_publish_job_context_playbook | Publish a version from the closed editor-subset document. Human job-manager court only. |
The server’s initialize response teaches this loop to every connected agent. The guide is also readable as Markdown through the resource opentrain://jobs/{jobId}/operations/agent-guide. The older opentrain://jobs/{jobId}/operations/guide resource and the opentrain_get_job_context_operating_guide tool return the canonical projection only and remain for existing clients.
import { OpenTrainClient } from "@opentrain-ai/sdk";
const client = new OpenTrainClient({ apiToken: process.env.OPENTRAIN_API_TOKEN! });
const { guide, markdown } = await client.getJobOperationsAgentGuide(jobId);const held = guide.playbook?.playbookVersion ?? 0;
// Later, when a covered response names recommendation.agent_guide_changed:const { delta } = await client.getJobOperationsPlaybookDelta(jobId, { fromVersion: held, toVersion: 5,});// delta.added, delta.changed carry full sections; delta.removedSectionIds are tombstones.
await client.submitJobOperationsPlaybookProposal(jobId, { kind: "SECTION_UPSERT", dedupeKey: "escalation.update", basePlaybookVersion: 5, title: "Clarify the escalation window", sectionId: "escalation", proposedSection: { level: 2, heading: "Escalation", markdown: "Ping the lead, then the PM within 10 minutes.", },});Also available: getJobOperationsPlaybook, listJobOperationsPlaybookVersions, getJobOperationsPlaybookVersion, listJobOperationsPlaybookProposals, resolveJobOperationsPlaybookProposal, and publishJobOperationsPlaybook. Keyed mutations send the Idempotency-Key header for you. getJobOperationsOperatingGuide returns the canonical projection alone and is kept for existing clients.
HTTP API
Section titled “HTTP API”All paths are relative to https://app.opentrain.ai/api/public/v1/job-operations/jobs/{jobId}.
| Method | Path | Purpose |
|---|---|---|
GET | /agent-guide | The composite Agent Guide: guide (typed projection, Playbook, open-proposal count, precedence, checksum) plus markdown. |
GET | /playbook | The published head, or the empty state when nothing is published. |
GET | /playbook/versions?limit= | Newest-first version summaries with per-version deltas. limit is 1 to 200. |
GET | /playbook/versions/{playbookVersion} | One exact version with its sections. 404 when it does not exist. |
GET | /playbook/delta?fromVersion=&toVersion= | Exact section delta: added, changed, removedSectionIds, unchangedSectionIds, sectionOrder. fromVersion 0 means everything is new; toVersion defaults to the head. |
GET | /playbook/proposals?status=&kind=&limit= | Oldest-first proposal listing with effective expiry and staleAgainstHead. |
POST | /playbook/proposals | Submit a proposal. Returns outcome of SUBMITTED, REPLAYED, or DEDUPLICATED. Requires Idempotency-Key. |
POST | /playbook/proposals/{proposalId}/resolve | ACCEPT, DECLINE, or WITHDRAW under expectedProposalRevision. Requires Idempotency-Key. |
POST | /playbook/publish | Publish a version from the closed editor-subset document under the expectedPlaybookVersion pin. Human job-manager court. Requires Idempotency-Key. |
GET | /guide | The canonical typed projection alone. Kept for existing clients. |
Mutations use the Idempotency-Key header. Replaying the same key with the same payload returns the original result with replayed: true; reusing a key for a different payload fails closed.
Publication body fields: expectedPlaybookVersion (the current head, 0 when none), optional expectedContextRevision, document, optional publicationNote (up to 2,000 characters), optional acceptProposalIds (up to 50 open proposal ids whose exact section content lands in this version), and optional agentLabel for an agent acting under a human token. Unchanged content is refused, and every response is the closed public version, never the editor document.
Handle refusals
Section titled “Handle refusals”| Situation | What OpenTrain returns | What to do |
|---|---|---|
basePlaybookVersion or expectedPlaybookVersion is not the head | A recoverable 409 carrying the current version. | Re-read the guide or delta, then resubmit against the current head. |
| A proposal was already resolved or expired | 409. | Read the proposal list; do not retry the resolution. |
The same dedupeKey already has a live open proposal | outcome: DEDUPLICATED with that proposal. | Treat it as your proposal; do not submit a duplicate. |
| An agent account tries to publish or accept a section proposal | A refusal with no existence disclosure. | Ask a human job manager to publish from the Agent Guide tab. |
| Accepted section content does not match what the version landed | Validation error naming the mismatched section and hashes; nothing is written. | Publish the exact proposed content or decline the proposal. |
Related
Section titled “Related”The concept: precedence, sections and hashes, deltas and tombstones, and automatic sync.
The context-first triage, claim, recheck, action, and handoff loop the guide sits inside.
The complete opentrain manager command family.
Every shared-context tool and the automatic initialize protocol.