opschain academy serve
packs:academy
opschain academy serve [flags]
Starts the installed OpsChain Academy agent against the targeted OpsChain
server. Co-located, the agent serves a whole team's learners on the lab
network: they open its pages, sign in with their company address, and the
agent attests on their behalf with its deployment key, registered on first
start through the grant file. With --single-learner it is the
learner-local lane on your own machine: you enrol once from its page and
your evidence is signed with your own key. Either way the learners do the
work through OpsChain itself; the agent reads the server's state and audit
events to check it and never writes.
The credential. The agent is a long-running reader, so the launcher
never hands it your login's access token (a few hours' credential, as
often expired as not). With a stored opschain login session for the
targeted server, the launcher first proves the session against the
server — a stale access token renews through the refresh token kept
beside it, exactly as every other command renews — and refuses an
expired login by name: your login for <server> has expired — run opschain login, or set OPSCHAIN_ACADEMY_TOKEN to an API token (opschain tokens create with a 720h expiry) (exit 2, nothing minted). It
then mints an API token of your own under the session — description
academy-agent <label> (--label / ACADEMY_AGENT_LABEL, else this
machine's hostname), expiring in 30 days, or at the agent's
--session-ttl when that reaches further — hands it to the agent as
OPSCHAIN_ACADEMY_TOKEN, announces the key's id and expiry on stderr
(never the value) and revokes it when the agent exits, whatever the
exit status. The launcher relays signals and waits for the agent, so a
stop by Ctrl-C or kill revokes it too; only a launcher killed outright
leaves the key to its expiry (opschain tokens list names it as
academy-agent <label>, opschain tokens revoke <id> retires it early).
The token carries your authority; the agent only ever reads with it.
OPSCHAIN_ACADEMY_TOKEN set in your environment is the explicit
override: handed to the agent as given — nothing checked, nothing
minted, nothing revoked. For an agent that runs unattended, set it to an
API token of a read-only user (opschain tokens create, 720h expiry):
the agent never needs a credential that could write.
What the licence unlocks. The agent gates every piece of content on
packs:academy, read back from the targeted server's licence: without it
no path is served and the page names the entitlement that unlocks the
academy. The Basic tier carries it and unlocks the Foundations track;
every other track is owned by a pack and opens with that pack's
entitlement — a track the licence lacks is shown locked, naming the pack,
and never holds back the tracks after it.
The tutor. The agent's optional tutor explains, diagnoses a failed
check from the examiner's verdicts and answers questions; it never grades,
and its model cost is never the estate's. The agent starts with no
model and serves the packs' hints; opschain academy mcp is the
learner-side lane, where your own MCP client tutors you on your
subscription; and --tutor <code> is the bring-your-own-provider lane,
wired from the estate's model-provider catalog (opschain docs model-providers):
the entry's kind picks the agent's adapter (anthropic and
azure-foundry-anthropic speak the Anthropic shape, openai and
openai-compatible the OpenAI shape; azure-openai is refused by name)
and its endpoint the base URL. An entry that is disabled or has no
data-handling approval recorded is refused before the agent starts — the
tutor sends learners' questions to the model. The catalog's stored
credential is never read: the model key is yours, in
ACADEMY_AGENT_TUTOR_KEY (or the variable --tutor-key-env names), and
must be present before the agent starts. --tutor and
--tutor-provider/--tutor-base-url are alternatives, not a mix.
The launcher wires the product in before the agent starts: the targeted
OpsChain server (--server, OPSCHAIN_SERVER or the active context —
never local mode) becomes the agent's OPSCHAIN_SERVER, and its
OPSCHAIN_ACADEMY_TOKEN is the scoped API token minted under your stored
opschain login session for that server — or the OPSCHAIN_ACADEMY_TOKEN
you set, handed over as given ("The credential", above). The agent only
ever reads with it. Without an installed agent, a server target, a
credential or an Academy Server (--academy-server, or
ACADEMY_AGENT_SERVER) the command refuses by name, and so does an
expired login.
Signals and exit. The agent runs in the foreground on this command's
streams and the launcher never exits ahead of it: an interrupt (Ctrl-C,
SIGINT) and a termination (SIGTERM — kill, a service manager's stop)
are relayed to the agent as they come, and a hangup (SIGHUP) is relayed
as a termination, so the agent shuts down on its own terms — it stops
serving and flushes its offline queue. The launcher then waits for it; an
agent that is still running 30 seconds after the signal is killed. The
agent's exit status becomes this command's; an agent ended by a signal
reports as a shell would, 128 plus the signal number.
Flags
Every flag maps onto the agent's own flag of the same meaning and its
ACADEMY_AGENT_* environment variable (a flag wins over the environment;
only flags you set are passed). --academy-server is the Academy Server,
distinct from the global --server, the OpsChain server the agent reads;
serve needs one, from the flag or ACADEMY_AGENT_SERVER.
| Flag | Meaning |
|---|---|
--tutor <code> | take the tutor's provider kind and endpoint from this model-provider catalog entry (code or id); launcher-only, the key stays in the environment |
--academy-server <url> | the Academy Server base URL (ACADEMY_AGENT_SERVER) |
--listen <addr> | address the learner pages listen on (default 127.0.0.1:8070; ACADEMY_AGENT_LISTEN) |
--data-dir <dir> | directory for the agent's store, deployment key and pack cache (default <opschain home>/academy; ACADEMY_AGENT_DATA_DIR) |
--grant-file <path> | file holding the registration grant, read at first run (ACADEMY_AGENT_GRANT_FILE) |
--key-file <path> | file holding the deployment key seed; default <data-dir>/deployment.key (ACADEMY_AGENT_KEY_FILE) |
--single-learner | the learner-local lane: one learner signing evidence with their own key (ACADEMY_AGENT_SINGLE_LEARNER) |
--label <text> | label shown to Academy administrators for this agent (ACADEMY_AGENT_LABEL) |
--session-ttl <duration> | browser sign-in lifetime, e.g. 12h (ACADEMY_AGENT_SESSION_TTL) |
--sync-interval <duration> | offline queue push and pack refresh interval, e.g. 30s (ACADEMY_AGENT_SYNC_INTERVAL) |
| `--tutor-provider anthropic | openai` |
--tutor-model <id> | the tutor model id; the provider's default when empty (ACADEMY_AGENT_TUTOR_MODEL) |
--tutor-base-url <url> | the tutor provider base URL; the provider's default when empty (ACADEMY_AGENT_TUTOR_BASE_URL) |
--tutor-key-env <name> | the environment variable holding the tutor model key (default ACADEMY_AGENT_TUTOR_KEY; ACADEMY_AGENT_TUTOR_KEY_ENV) |
--secure-cookies | mark the learner session cookie Secure, behind TLS (ACADEMY_AGENT_SECURE_COOKIES) |
Examples
$ opschain academy serve --single-learner --academy-server https://academy.limepoint.com --grant-file ~/academy-grant
$ ACADEMY_AGENT_TUTOR_KEY=sk-… opschain academy serve --single-learner --tutor claude-lab \
--academy-server https://academy.limepoint.com --grant-file ~/academy-grant
$ OPSCHAIN_ACADEMY_TOKEN=ocak_… opschain academy serve --server https://ops.example.com \
--academy-server https://academy.limepoint.com --grant-file /var/lib/academy/grant \
--data-dir /var/lib/academy --listen 0.0.0.0:8070 --label lab-east --secure-cookies
Exit codes: the agent's own exit status (128 plus the signal number when
a signal ended it); 2 when no agent is installed, no server is targeted,
no credential is available, the stored login has expired or no Academy
Server is named (the message names the fix); 1 when the server refused
to mint the agent's token. On stderr, before the agent's own output:
minted api key <id> (academy-agent <label>) for the agent, expires <time> — revoked when the agent exits, and after it revoked the agent's api key <id> (or, when the revocation did not land, the key's id and expiry with
the opschain tokens revoke command).
See also
opschain docs cli/academy— the command family and a first session.opschain docs packs-academy— the lanes, the evidence model and the tutor.