Skip to main content

Open Agent Guide client

oag is the command-line client for Open Agent Guide. It validates catalog proposals, submits them, and watches them. Catalog proposals are immutable. The same open-agent-guide package also ships oag_client, a typed Python library. The library runs the same workflows in process. It does not start a subprocess. It does not need a Django install.

Install

The client supports macOS and Linux on Python 3.12, 3.13, or 3.14.

pip install open-agent-guide        # library + oag CLI
uv tool install open-agent-guide    # isolated CLI install

To upgrade, run pip install --upgrade open-agent-guide or uv tool upgrade open-agent-guide. To use the library in a project, run uv add open-agent-guide. The client does not support Windows yet. The client does not support standalone executables yet.

Tutorial: getting started

This tutorial shows one first run from start to end. You set your token, then you validate, submit, and watch a batch.

Set your bearer token. Generate a token in your account settings.

export OAG_TOKEN=...

Validate the batch. Validation calls the server and reports its field-path errors.

oag validate batch.json --output json

Submit the batch. Write a submit journal with --journal. The journal lets you resume the batch and reconcile it later.

oag submit batch.json --journal batch.journal.json --output json

Watch the submissions. Write a watch journal with --journal. Set an overall timeout. The client polls each unresolved submission until it reaches a terminal state.

oag watch --file ids.txt --journal watch.journal.json --timeout 900 --output jsonl

OAG_BASE_URL defaults to https://www.openagentguide.com. Point it at a staging origin to test. OAG_BASE_URL cannot contain credentials. It cannot contain a path, a query, or a fragment. Bearer tokens never appear in transport diagnostics. The client does not follow redirects.

How-to guides

Submit a batch and watch it

  1. Validate the batch: oag validate batch.json --output json.
  2. Submit the batch with a journal: oag submit batch.json --journal batch.journal.json --output json.
  3. Watch the submissions with a journal and a timeout: oag watch --file ids.txt --journal watch.journal.json --timeout 900 --output jsonl.

Use one pacing directory for concurrent validate, submit, and watch commands.

Explain a rejection

Run status or watch with --output explain to read why a submission needs work.

oag status 00000000-0000-0000-0000-000000000001 --output explain

--output explain (-o explain) drops the full record dump. It prints a compact, line-based explanation of each result. The explanation shows the lifecycle state, the next-action guidance, the terminal resolution, and any successor IDs. For each failed or errored check, it shows the headline summary. Under each summary, it shows every unsupported claim with its verdict, its specific reason, and its citation URLs. It ends each check with its decision basis. The view keeps the specific claim-level reason that a repair depends on in view. It does not show only the broad diagnostic category. The view reads only the fields that the read API already returns to you. These fields are guidance, resolution, and the scrubbed check_feedback projection. The view makes no extra server call. The json and jsonl contracts stay unchanged. The journal format stays unchanged.

Retire a submission

retire withdraws or supersedes one of your open submissions.

  • To withdraw the proposal, pass no --successor option.
  • To supersede the proposal, pass one or more --successor UUID options. Each option names an explicit newer replacement.
  • To record an optional reason, pass --reason TEXT.
oag retire 00000000-0000-0000-0000-000000000001 --force --reason "stale"
oag retire 00000000-0000-0000-0000-000000000001 --force --successor UUID --output json

retire requires --force. Without --force, it refuses, sends nothing, and exits 2. A success reports the server's disposition (withdrawn or superseded) and exits 0. The command does not poll afterward. Use status or watch to follow the retired submission and its successors. See the retire entry under Reference for the full behavior and the server rules.

Recover after a timeout and reconcile a journal

A watch timeout does not mean a submission failed. Resume its journal. Inspect the lifecycle and the terminal evidence.

Reuse the original submit journal and idempotency keys after an uncertain create. Never start a duplicate batch to beat a deadline.

A pacing timeout reports the lane, the reserved wait, the remaining budget, and the requests that the client sent. Submit journals keep this diagnostic with the original idempotency key. Watch adds deadline_error to unresolved records and saves it in the watch journal. Watch keeps earlier read errors and submission snapshots. Resume the same journal with a larger budget after you investigate shared load. Never clear the pacing file to skip a cooldown. Never delete the journal to retry uncertain submissions.

Some older entries have no keys. The client cannot replay them safely. Inspect your submissions on the server across all statuses. Compare the complete payload and the submitter. Once you positively identify an ID, associate it with the input row:

oag reconcile batch.json --journal batch.journal.json --row 2 --id UUID

This checks that the ID is readable. You verify the row-to-ID match. It does not create or edit a server submission. If no match turns up, absence is not proof of failure. Reconcile with an administrator before you create a new batch and journal. A server 409 idempotency_key_reused also needs inspection. Do not mint a fresh key for the uncertain write. The effective callback URL must stay the same for a retry. A change to a token's default callback can cause that conflict.

For a definitively failed row, correct the payload. Submit a new batch with a new journal. Existing submissions are immutable. To supersede a stalled open create, inspect the existing submission. Then set "force": true in a new payload and submit with a new journal. The client never adds force. The client never edits an existing proposal. Keep prior journals for audit.

Research a product's coverage gaps

Run oag coverage PRODUCT --output json for one compact report of a product's coverage and its unknown scored fields. The default text output adds evidence guidance. The equivalent reads are GET /api/v1/catalog/products/{uuid-or-slug}/coverage/ and the MCP tool get_product_coverage. Read each gap's shared semantics, its schema reference, and its absence page class before you draft. Keep unsupported values unknown. A confirmed absence can improve coverage without improving the AI-native score. Use submission validation to inspect projected changes after you collect evidence.

Share pacing across workers

The oag CLI shares reservations and Retry-After cooldowns across processes on one host. The processes must use the same pacing directory, the same API origin, and the same token. The population benchmark and the pi submitter opt into the same coordination. Python Client instances pace in process unless you pass shared_pacer(base_url, token).

The default directory is oag-client-pace under the system temp directory. Set OAG_PACING_DIR to choose another directory. Cooperating processes must share that directory, that base URL, and that token. The filename hashes the origin and a one-way token fingerprint. The file stores timestamps. The file never stores the raw token. A crash releases the file lock but keeps its recorded reservations. Separate directories, hosts, origins, or tokens do not share state. Server quotas apply account-wide across all of an account's tokens, so coordinate those workers yourself. Shared pacing cuts collisions. It does not guarantee that requests dodge throttling.

A transient 429 extends the shared cooldown to the longest value that any cooperating process reports. Workers recheck the cooldown after they wait for a reserved slot. The client honors numeric and HTTP-date Retry-After values within the workflow deadline, across reads and mutations together. Workers outside the shared state must pause every worker on the exhausted X-RateLimit-Scope for at least Retry-After seconds, with jitter, before they resume. The scopes are global_auth for reads, and submission and submission_burst for submission mutations. The open-submission-cap 429 returns immediately without a retry.

Use trusted bulk read pacing

Default read spacing is 0.55 seconds. A maintainer can grant your account the submissions.bulk_submit_catalogsubmission permission. With that permission, set OAG_READ_SPACING=0.11 for the CLI, or pass read_spacing=0.11 to shared_pacer(base_url, token, ...). That targets about 545 reads per minute under the server's default 600-per-minute trusted read quota (BULK_AUTHENTICATED_READ_RATE). Use the same spacing, the same token, and the same OAG_PACING_DIR for coordinated workers on one host. Keep status reads batched through watch. Separate tokens for one account share the quota but need caller-managed coordination. Restore 0.55 seconds after a revocation. The server checks permission on each request. Clients keep honoring shared Retry-After cooldowns. Create and validate spacing stays 3.5 seconds. Review, merge, close, and retire writes keep a separate 0.55-second minimum even with faster reads. Custom Pacer.reserve implementations must accept global_mutation=False.

Reference

Command synopsis

oag --version
oag validate batch.json --output json
cat batch.json | oag validate - --output jsonl
oag submit batch.json --journal batch.journal.json --output json
oag status 00000000-0000-0000-0000-000000000001 --output json
oag status 00000000-0000-0000-0000-000000000001 --output explain
oag watch --file ids.txt --journal watch.journal.json --timeout 900 --output jsonl
oag watch 00000000-0000-0000-0000-000000000001 --journal watch-one.json
oag retire 00000000-0000-0000-0000-000000000001 --force --reason "stale"
oag retire 00000000-0000-0000-0000-000000000001 --force --successor UUID --output json
oag get /api/v1/catalog/products/?page_size=50
oag get https://www.openagentguide.com/api/v1/catalog/products/?page=2

oag --version (-V) prints the installed version and exits 0.

validate and submit

validate and submit take one JSON object or an array. The input comes from a file or from - for stdin. Nested relation envelopes and explicit nulls pass through unchanged. Omitted keys stay omitted. Validation calls the server and returns its field-path errors. It does not probe external citation URLs. The batch preflight script still covers that separate check.

status and watch

status fetches one submission with all its checks and reviews pages. watch polls unresolved IDs in batches of up to 100 (ids=...&page_size=100&fields=id,status,review_ready,check_feedback,guidance). Pending records hold that compact snapshot. When an ID goes terminal, watch fetches its full detail and every checks and reviews page. Watch keeps claim verdicts, rationales, citations, and resolution reasons.

Only lifecycle merged counts as accepted. An ordinary closed is rejected. Closed proposals with a retirement disposition report withdrawn or superseded. Replacement IDs appear in resolution.closed.successor_ids. A check error on an open submission stays pending. A failed detail read or evidence read becomes failed-to-read, even after a terminal lifecycle was seen. Watch retries unresolved records in later rounds. Watch stops revisiting a terminal record only after it captures the record's evidence. The journal keeps those terminal snapshots across restarts. Start a fresh journal for a fresh view of later evidence. Missing batch IDs stay failed-to-read. The server must support the ids filter.

retire

retire withdraws or supersedes one of your open submissions. With no --successor option it withdraws the proposal. One or more --successor UUID options supersede it with those explicit newer replacements. --reason TEXT records an optional reason. retire makes one request. It never retries. It never runs on its own. --force is required. Without --force, retire refuses, sends nothing, and exits 2. The tool never withdraws or supersedes on your behalf. The server enforces author-or-curator permission. The server enforces newer-only successors. A success reports the server's disposition (withdrawn or superseded) and exits 0. A 403 or a validation error exits 3. The command does not poll afterward. Use status or watch to follow the retired submission and its successors.

get

get PATH reads one catalog or submissions read-API path through the shared read pacing lane and prints the JSON body. PATH is a relative read-API path or a same-origin absolute URL. You can pass a pagination next link straight back without stripping its origin. The client accepts an absolute PATH only when its scheme and host match OAG_BASE_URL with no userinfo. A foreign origin, userinfo, an unsupported scheme, or a path outside the catalog or submissions read API exits 2 without a request. Catalog reads work anonymously. The submissions field contract needs OAG_TOKEN.

Reading guidance

status and watch request guidance and keep its next_action code. For direct API reads, request guidance alongside status, resolution, and check_feedback. The codes:

  • wait: keep watching.
  • prepare_correction: prepare the repair now, but wait for terminal closure before you submit it.
  • revise_and_resubmit: inspect the rejection, correct the proposal, then validate against the current catalog.
  • none: read the terminal resolution, including any successor links.

Guidance never reserves an identity. Guidance never bypasses create conflicts. If guidance is absent, fall back to lifecycle status. Never infer rejection from a check error. Preserve your submit and watch journals.

Output formats

Every command takes --output text|json|jsonl|explain. JSON holds version, records, and summary. JSONL emits one type: record line per result, then a type: summary line. Output lands at completion, including watch cancellation. Watch also emits changed next-action guidance to stderr as it runs. Text prints the full record with indented evidence. Then text lists any check feedback and absence-attestation guidance, one scannable line each. You see why a row needs work without digging through the JSON. Diagnostics go to stderr. No command prompts.

A failed read keeps the server's structured error. Every failed-to-read record carries a failure object with a kind. The kind is http, deadline, transport, or client. An http failure also carries http_status, plus the server's code, detail, and validation errors when present. The human-readable error string stays too. coverage wraps the same object in a {"version": 1, "error": {...}} envelope on failure and exits 3. Its successful report is unchanged.

Exit codes

Exit Meaning
0 Validation/submission succeeded, or all watched records are terminal
2 Invalid arguments, configuration, input, or journal
3 At least one failed/ambiguous batch row or failed-to-read record
4 Pending records remain at the deadline or in one-shot status
5 All records were read, but --require-all-merged found a rejection
130 Cancelled by Ctrl-C

Failures outrank pending records. Pending records outrank --require-all-merged. By default a fully read rejection exits 0, because watching finished. Pass --require-all-merged to status or watch to require acceptance. Summaries always separate accepted, rejected, pending, and failed-to-read. Batch summaries also count valid, created, failed, and ambiguous rows.

Pacing and deadlines

--timeout is an overall seconds budget. It is 300 for validate and submit, 60 for status, and 900 for watch. It covers pacing waits, requests, retries, and cooldowns. Watch pauses 15 seconds between rounds. Ctrl-C ends watch with a final summary and exit 130. Its journal can resume. A hard kill cannot emit a summary.

The client spaces reads 0.55 seconds apart and mutations 3.5 seconds apart. Validation POSTs use the mutation pace. Requests have a 45-second budget, capped by the remaining workflow deadline. Validation and keyed creates retry transport failures, 5xx, and transient 429s, up to five attempts. Unkeyed writes retry only transient 429s. Polling makes one attempt per round.

Future mutation reservations leave the read schedule unchanged. Create and validate use the mutation lane. Globally throttled writes such as review, merge, close, and retire share the read lane. If a peer extends Retry-After during a wait, the worker reserves a fresh slot to keep spacing after the cooldown. Cancelled or expired reservations stay on their lane until their slots pass. Restart preserves them.

Sizing batches

Size batches against the combined workload. Fifty validation POSTs followed by fifty create POSTs need about 350 seconds of mutation spacing alone, before network time, retries, cooldowns, or other workers' reservations. Those are separate command budgets. Raise --timeout per command for its share of the work. Leave extra time for watch to capture terminal evidence. More concurrent processes do not raise shared throughput. Prefer smaller batches, fewer simultaneous validators and submitters, and one watcher per account that holds all unresolved IDs. Use one pacing directory for concurrent validate, submit, and watch commands.

Environment variables

  • OAG_TOKEN: the bearer token. Generate one in your account settings. Catalog reads work without it. The submissions field contract needs it.
  • OAG_BASE_URL: the API origin. It defaults to https://www.openagentguide.com. It cannot contain credentials, a path, a query, or a fragment.
  • OAG_PACING_DIR: the pacing directory. It defaults to oag-client-pace under the system temp directory. Cooperating processes must share it.
  • OAG_READ_SPACING: the read spacing in seconds. The default is 0.55. Set it to 0.11 with the submissions.bulk_submit_catalogsubmission permission.

Python API

from oag_client import Client, shared_pacer
from oag_client.transport import HTTPTransport
from oag_client.workflows import payloads, validate

base_url = "https://www.openagentguide.com"
# Omit `pacer` for in-process pacing; pass `shared_pacer` to coordinate with
# other processes on this host that share the token.
client = Client(HTTPTransport(token), base_url, pacer=shared_pacer(base_url, token))
records = validate(client, payloads(json_text), deadline=client.clock.monotonic() + 60)

submit, status, watch, summary, and exit_code also come from oag_client.workflows. Journal lives in oag_client.journal. The Clock and Transport protocols make testing deterministic. A custom transport must accept the optional idempotency_key keyword and forward it as Idempotency-Key on create requests. The HTTP transport is synchronous, so async callers should use a worker thread. Application code supplies authorization. Pacing is in process by default. Pass shared_pacer(base_url, token) (or any Pacer) to coordinate processes that share a directory, an origin, and a token on one host. Coordinate other tokens or hosts yourself, because server quotas cover the whole account.

Explanation

How journals and idempotency keys keep submissions safe to retry

Always reuse the same submit journal for a batch. The journal binds the ordered input hash, the base URL, and the token fingerprint. Changed inputs, environments, or tokens fail instead of replaying. The journal never stores tokens. The journal holds server evidence and may hold private submission data, so keep it private.

Each new row gets a random UUID Idempotency-Key. The client flushes the key to the journal before the first POST. Every attempt and restart reuses that key and the same input. A confirmed 201 records the original submission ID as created, even if the server already merged or closed it. The client skips confirmed and definitively failed rows on restart. Keyed ambiguous or pending rows retry within the command's deadline. Exhausted transient failures stay unresolved.

Journal writes are atomic and flushed to disk. A lock prevents simultaneous writers. After a hard kill, confirm that no writer remains before you delete the .lock file. Never delete a journal to recover from a timeout. Never change a journal's keys to recover from a timeout. A deadline or cancellation after an uncertain attempt preserves its key.

The client uses semantic versioning. JSON output stays version 1. New and saved journals use version 2. Version-1 journals stay readable, but unkeyed uncertain rows need manual reconciliation. Older clients reject version-2 journals. An upgrade alone never sends requests and never rewrites journals. Running submit resumes keyed uncertain rows. Pair the client with a server that supports the create Idempotency-Key contract.

How shared pacing and deadlines work

The client spaces reads and mutations to stay under the server's quotas. The oag CLI shares reservations and Retry-After cooldowns across processes on one host when the processes use the same pacing directory, API origin, and token. The filename hashes the origin and a one-way token fingerprint, so separate directories, hosts, origins, or tokens do not share state. The file stores timestamps, never the raw token. A crash releases the file lock but keeps its recorded reservations, so a restart preserves them.

A transient 429 extends the shared cooldown to the longest value that any cooperating process reports. The client honors numeric and HTTP-date Retry-After values within the workflow deadline, across reads and mutations together.

Shared pacing cuts collisions. It does not guarantee that requests dodge throttling. Server quotas apply account-wide across all of an account's tokens, so coordinate separate tokens and separate hosts yourself. More concurrent processes do not raise shared throughput. The open-submission-cap 429 returns immediately without a retry.

A watch timeout does not mean a submission failed. Resume the journal and inspect the lifecycle and the terminal evidence. The journal and the idempotency keys make an uncertain create safe to retry without a duplicate.

Metadata

Release files for open-agent-guide 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for open-agent-guide 0.6.0
File Size Uploaded Provenance Actions
open_agent_guide-0.6.0.tar.gz 51.2 kB With provenance Details for open_agent_guide-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for open-agent-guide 0.6.0
File Interpreter ABI Platform Actions
open_agent_guide-0.6.0-py3-none-any.whl Python 3 none any Details for open_agent_guide-0.6.0-py3-none-any.whl

Total release size: 90.5 kB

Release files / open_agent_guide-0.6.0.tar.gz

Download URL open_agent_guide-0.6.0.tar.gz
Size 51.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b04abb2feb76dfb77681befb648fa8fbe084de34b99391e7cbd05caa5dfe50e0
BLAKE2b-256 checksum
How to use checksums
9255cc24a5c85a82e7a03ae3c3a1b0dce804f5a562ce8cf5a9f9dc571559285f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / open_agent_guide-0.6.0-py3-none-any.whl

Download URL open_agent_guide-0.6.0-py3-none-any.whl
Size 39.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bb5cbe17f577df53f1425780f7410499374f8d8812f5fb78efba426628f646dd
BLAKE2b-256 checksum
How to use checksums
2f07b6480f28d651aceed92e029ef924d82b2cd48107e49af02bcb4caab172a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for open-agent-guide 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for open_agent_guide-0.6.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page