Guides
Handle every verdict
Client code that branches correctly on all three outcomes and on the refusals around them.
The mistake to avoid is collapsing three different situations into one
try/except. A refusal, an outage and a spent allowance need three different
responses, and two of them should never reach a retry loop.
The shape
import httpx
def ask(intent: str, oracle: str = "chart") -> dict:
r = httpx.post(
f"{BASE}/v1/oracles/{oracle}/ask",
headers={"Authorization": f"Bearer {KEY}"},
json={"intent": intent},
timeout=120, # a verdict can take this long
)
# ---- refusals: the request never reached an oracle -----------------
if r.status_code == 401:
# KEY_MISSING / KEY_UNKNOWN / KEY_REVOKED / KEY_EXPIRED.
# A human has to act. Never retry.
raise Fatal(r.json()["error"])
if r.status_code == 402:
# QUOTA_EXCEEDED. The credential is fine; the allowance is spent.
# A different key will not help — quota is per organisation.
raise OutOfCredits(r.json()["context"])
if r.status_code == 404:
raise Fatal("no such oracle — read GET /v1/oracles")
if r.status_code == 422:
# Includes "this oracle cannot produce that format", and the
# response names the ones it can.
raise Fatal(r.json())
r.raise_for_status()
# ---- verdicts: an oracle ran -------------------------------------
answer = r.json()
if answer["status"] == "error":
return retry_with_backoff() # ours, unbilled
if answer["status"] == "invalid":
return rejected(answer["detail"]) # billed, and a real answer
return answer["result"] # store verified_by with itThe distinctions that matter
402 is not 401. Your credential is fine. A client that treats a spent
quota as an auth failure re-prompts a human for a key that was never the problem.
invalid is not an exception. It is the product working. Surface it to
whoever asked, do not swallow it, and do not retry the identical intent hoping
for a different roll.
error is the only thing worth retrying automatically, and it is free.
Store the citation
save(artifact=answer["result"], checked_against=answer["verified_by"])