Open Agent Guide client
oag 0.3.1 requests guidance automatically. For direct API reads, request
guidance alongside status, resolution, and check_feedback when reading
your submissions. guidance.next_action=wait means keep watching;
prepare_correction means prepare the repair now but wait for terminal closure
before submitting it. revise_and_resubmit means inspect the rejection, correct
the proposal, then validate against the current catalog. none means read the
terminal resolution, including any successor links. Guidance never reserves an
identity or bypasses create conflicts. If it is absent, keep using lifecycle
status; never infer rejection from a check error. Preserve submit/watch
journals.
oag validates, submits, and watches immutable catalog proposals. The Python
library runs the same workflows without a subprocess or Django installation.
Install and upgrade
Supported platforms are macOS and Linux with Python 3.12, 3.13, or 3.14. Obtain the versioned wheel from your administrator, then install it:
uv tool install --force ./open_agent_guide-*.whl
# Upgrade explicitly when given a newer wheel:
uv tool install --force ./open_agent_guide-*.whl
For library use, uv add ./open_agent_guide-*.whl. Maintainers build with
uv build --package open-agent-guide and can install from
./packages/oag-client. CI smoke-tests clean wheel installation on both
supported operating systems. The package is MIT-licensed. Public PyPI
publication as open-agent-guide is planned; until then contact
support@openagentguide.com for distribution. Windows and standalone
executables are not supported yet.
Package versions follow semantic versioning. JSON output remains version 1; new
and saved journals use version 2. Version-1 journals remain readable, but
unkeyed uncertain rows require manual reconciliation. Older clients reject
version-2 journals. Upgrading alone never sends requests or rewrites journals;
explicitly running submit resumes keyed uncertain rows. Use oag-client 0.2.0
or newer with a server that supports the create Idempotency-Key contract.
Commands
Export OAG_TOKEN with your bearer token. OAG_BASE_URL defaults to
https://www.openagentguide.com; set it to your staging origin for testing. The
base URL cannot contain credentials, a path, query, or fragment. Bearer tokens
never appear in transport diagnostics. Redirects are not followed.
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 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
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, so a pagination next link can be passed straight
back without stripping its origin. An absolute PATH is accepted 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.
oag --version (-V) prints the installed version and exits.
validate and submit accept one JSON object or an array, from a file or -
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. Validation does not probe external citation URLs; the
existing batch preflight script remains available for that separate check.
Every command accepts --output text|json|jsonl. JSON contains version,
records, and summary; JSONL emits one type: record line per result
followed by a type: summary line. Output is emitted at completion, including
watch cancellation. Version 0.3.1 emits changed next-action guidance to stderr
during watch. Text includes the complete record with indented evidence, then
lists any check feedback and absence-attestation guidance as one scannable line
each so a reader sees why a row needs work without searching the JSON.
Diagnostics go to stderr. No command prompts.
status fetches one submission with all checks and reviews pages. In 0.3.1,
watch polls unresolved IDs in batches of up to 100 using
ids=...&page_size=100&fields=id,status,review_ready,check_feedback,guidance.
Pending records contain this compact submission snapshot. When an ID becomes
terminal, watch fetches its full detail and all checks and reviews pages,
preserving claim verdicts, rationales, citations, and resolution reasons.
Missing batch IDs remain failed-to-read. The server must support the ids
filter. Only lifecycle merged means accepted; ordinary closed means
rejected. Closed proposals with retirement dispositions report withdrawn or
superseded, with replacement IDs in resolution.closed.successor_ids. A check
error on an open submission remains pending. A failed detail or evidence
request means failed-to-read, including when a terminal lifecycle has been
seen. Watch retries unresolved records in later rounds and stops revisiting
terminal records only after capturing their evidence. The journal preserves
those terminal snapshots on restart. Use a fresh journal for a fresh view of
later evidence.
retire withdraws or supersedes one of your open submissions through the
server's retirement operation. With no --successor it withdraws the proposal;
one or more --successor UUID options supersede it with those explicit newer
replacement IDs, and --reason TEXT records an optional reason. The command
makes one request and never retries or runs automatically. --force is
required: without it retire refuses, makes no request, and exits 2, so the
tool never withdraws or supersedes on your behalf. The server still enforces
author-or-curator permission and newer-only successors. A successful retire
reports the server's terminal disposition, withdrawn or superseded, and
exits 0; a 403 or validation error exits 3. The command does not poll afterward;
use status/watch to observe the retired submission and its successors.
A failed read keeps the server's structured error. Every failed-to-read record
carries a failure object with a kind (http, deadline, transport, or
client); an http failure also carries http_status, and the server's
code, detail, and validation errors when present. The human-readable
error string stays as well. coverage wraps the same object in a
{"version": 1, "error": {...}} envelope on failure and exits 3; its successful
report is unchanged.
Pacing and workflow deadlines
--timeout is an overall seconds budget, default 300 for validate/submit, 60
for status, and 900 for watch. It includes 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 be resumed. Hard kills cannot emit a
summary.
The client spaces reads by 0.55 seconds and mutations by 3.5 seconds. Validation
POSTs use the mutation pace too. The oag CLI shares reservations and
Retry-After cooldowns across processes on one host that use the same pacing
directory, API origin, and token. The maintained population benchmark and pi
submitter also opt into this coordination. Python Client instances use local
pacing unless you pass shared_pacer(base_url, token).
The default directory is oag-client-pace under the system temp directory;
OAG_PACING_DIR selects another directory. All cooperating processes must reach
the same directory and use the same base URL and token. The filename hashes the
origin and a one-way token fingerprint; the file stores timestamps, never the
raw token. A process crash releases the file lock, but its recorded reservations
remain. Separate directories, hosts, origins, or tokens do not share this state.
Server quotas apply account-wide across all of an account's tokens, so
coordinate those workers yourself. Shared pacing reduces collisions; it does not
guarantee that requests avoid throttling.
A transient 429 extends the shared cooldown, keeping the longest cooldown
reported by any cooperating process. Workers check it again after waiting for a
reserved slot. Numeric and HTTP-date Retry-After values are honored within the
workflow deadline. This cooldown applies to reads and mutations together. For
workers outside that shared state, pause every worker using the exhausted
X-RateLimit-Scope for at least Retry-After seconds and add jitter before
resuming. The scopes are global_auth for reads, and submission and
submission_burst for submission mutations. The open-submission-cap 429 returns
immediately without retrying.
Size batches against the combined workload. Fifty validation POSTs followed by
fifty create POSTs require about 350 seconds of mutation spacing alone, before
network time, retries, cooldowns, or other workers' reservations. Those are
separate command budgets: increase --timeout for each command based on its
share of the work, and allow additional time for watch to capture terminal
evidence. More concurrent processes do not increase shared throughput. Prefer
smaller batches, fewer simultaneous validators/submitters, and one watcher per
account with all unresolved IDs. Use the same pacing directory for concurrent
CLI validation, submission, and watch commands.
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 preserve spacing after the cooldown. Cancelled or expired reservations remain on their lane until their slots pass; restart preserves those reservations and cooldowns. Watch budgets also need time for server processing, poll intervals, and terminal evidence reads across all watchers. Shared pacing neither bounds outstanding server work nor eliminates deadline failures. A watch timeout does not mean a submission failed: resume its journal and inspect lifecycle and terminal evidence. Reuse the original submit journal and idempotency keys after an uncertain create; never start a duplicate batch to escape a deadline.
Requests have a 45-second total budget capped by the remaining workflow
deadline. Validation and keyed creates retry transport failures, 5xx, and
transient 429 responses, at most five attempts. Unkeyed writes retry only
transient 429 responses. Exhausted HTTP failures retain http_status alongside
the response. Polling makes one attempt per round. Keep terminal evidence in the
journal and remove those IDs from future polls.
A pacing timeout reports the lane, reserved wait, remaining budget, and requests
sent by that client. Submit journals retain this diagnostic with the original
idempotency key. Watch adds deadline_error to unresolved records and saves it
in the watch journal, preserving earlier read errors and submission snapshots.
Resume the same journal with a larger budget after investigating shared load.
Never clear the pacing file to bypass a cooldown or delete the journal to retry
uncertain submissions.
| 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 take precedence over pending records, which take precedence over
--require-all-merged. By default, a fully read rejection exits 0: watching has
completed. Use --require-all-merged on status/watch to require acceptance.
Summaries always distinguish accepted, rejected, pending, and failed-to-read;
batch summaries also count valid, created, failed, and ambiguous rows as
present.
Resume and reconcile
Always reuse the same submit journal for the same batch. It binds the ordered input hash, base URL, and token fingerprint; changed inputs, environments, or tokens fail rather than replay. Tokens themselves are never stored. The journal contains server evidence and may contain private submission data. Keep it private.
Each new row gets a random UUID Idempotency-Key, flushed to the journal before
its 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 has already merged or closed it. Confirmed and definitively failed rows
are skipped on restart. Keyed ambiguous or pending rows are retried within the
command's deadline. Exhausted transient failures remain unresolved.
Journal writes are atomic and flushed to disk. A lock prevents simultaneous
writers; after a hard kill, verify no writer remains before deleting the .lock
file. Never delete a journal or change its keys to recover from a timeout. A
deadline or cancellation after an uncertain attempt preserves its key.
Older entries without keys cannot be replayed safely. Inspect your submissions on the server, including all statuses, and compare the complete payload and submitter. After positively identifying 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; the operator verifies the row-to-ID match.
It does not create or edit a server submission. If no match can be found,
absence is not proof of failure. Reconcile with an administrator before creating
a new batch and journal. A server 409 idempotency_key_reused also requires
inspection, not a fresh key for the uncertain write. The effective callback URL
must remain unchanged for a retry; changing a token's default callback can cause
that conflict.
For a definitive failed row, correct the payload and explicitly submit a new
batch with a new journal. Existing submissions are immutable. To supersede a
stalled open create, inspect the existing submission first, then explicitly set
"force": true in a new payload and submit with a new journal. The client never
adds force or edits an existing proposal. Preserve prior journals for audit.
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 are also available from
oag_client.workflows; Journal lives in oag_client.journal. Clock and
Transport protocols allow deterministic testing. Custom transports must accept
the optional idempotency_key keyword and forward it as Idempotency-Key for
create requests. The HTTP transport is a synchronous entry point; 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 using the same directory, origin, and token on one host.
Coordinate other tokens or hosts yourself because server quotas cover the whole
account.
Trusted bulk read pacing
The default read spacing is 0.55 seconds. If a maintainer has granted your
account submissions.bulk_submit_catalogsubmission, set OAG_READ_SPACING=0.11
for the CLI, or pass read_spacing=0.11 to
shared_pacer(base_url, token, ...). This targets about 545 reads/minute under
the server's default 600/minute trusted read quota. The server setting is
BULK_AUTHENTICATED_READ_RATE.
Use the same spacing, token, and OAG_PACING_DIR for coordinated workers on one
host. Keep status reads batched through watch; more quota doesn't require
polling each submission separately. Separate tokens for one account share the
server quota but need caller-managed pacing coordination. After permission
revocation, restore 0.55 seconds. The server checks permission on each request
and clients continue to honor shared Retry-After cooldowns.
Create/validate spacing stays at 3.5 seconds. Review, merge, close, and retire
writes keep a separate 0.55-second minimum interval even with faster reads.
Custom Pacer.reserve implementations must accept global_mutation=False.
Research an existing product's gaps
Use oag coverage PRODUCT --output json for one compact report of the product's
coverage and unknown scored fields. The default text output includes 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, schema reference, and
absence page class before drafting. Keep unsupported values unknown. A confirmed
absence can improve coverage without improving the AI-native score. Use
submission validation to inspect projected changes after collecting evidence.
Metadata
Release files for open-agent-guide 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| open_agent_guide-0.5.0.tar.gz | 47.4 kB | With provenance | Details for open_agent_guide-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| open_agent_guide-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for open_agent_guide-0.5.0-py3-none-any.whl |
Total release size: 84.3 kB
Release files / open_agent_guide-0.5.0.tar.gz
| Download URL | open_agent_guide-0.5.0.tar.gz |
|---|---|
| Size | 47.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
69575473e3e52b9930e461369b9e5c7c6831cdcd127a09484d81d963909eafe4
|
|
BLAKE2b-256 checksum How to use checksums |
a955ae929759677ca5ac9dca9704d539d47dfa6c5312c7ed0f8df74ae1daa0f4
|
| 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 logRelease files / open_agent_guide-0.5.0-py3-none-any.whl
| Download URL | open_agent_guide-0.5.0-py3-none-any.whl |
|---|---|
| Size | 37.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fb237305d27f1621f5e19897c713347e4f428271f13f89152b75725f3b4b4e61
|
|
BLAKE2b-256 checksum How to use checksums |
93950045ecb5116bf83d4b1de8228d1bdd5dab200383259427a1f2033c709c30
|
| 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 logSecurity for open-agent-guide 0.5.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.
Attestation for open_agent_guide-0.5.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 logA 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.