v0.13.2 — a refused manifest no longer costs the trace
Added
-
smart_route()now names WHY it returned an empty menu:degraded_reasonishttp_<status>/timeout/circuit_open/transport, so a caller can tell a Cloud Run edge abort (a 0 s 429) from a slow read or an open breaker instead of filing every empty menu as "no skill offered". -
decimalai init --framework adkwrites a runnable Google ADK agent:
Gemini by default (gemini-3.5-flash; a non-Gemini--modelis refused up
front, becausedecimalai[adk]installs no other provider), aGOOGLE_API_KEY
guard on line one, and skills delivered by prompt injection through
instrument(agent_name=..., enable_skill_loader=True). The template was
withheld on the premise that the hermetic J1 journey could not stand in for
Gemini; that premise was false — google-genai honoursGOOGLE_GEMINI_BASE_URL
(since v1.72, google-adk 2.0.0's own floor), so the journey stub now speaks
:generateContentand grades the ADK cell like the other three. Nothing in
the generated file knows about the stub. -
Every generated file refuses to run without the provider key its
MODEL
needs, naming the variable and theSet:blockdecimalai initprinted.
Before, a missingOPENAI_API_KEYwas a traceback from inside the provider
client — afterinit(),instrument()andload_agent()had already made
their network calls (onopenai-agents, only at the firstRunner.run_sync).
The guard is derived from the same tables as theSet:block and is omitted
where those tables only guess (a local provider, Pydantic AI'stestmodel, an
unknown prefix such asazure_openai:), so it never refuses a correct setup. -
The
langchaintemplate says at the call site thatcreate_agentruns with
recursion_limit=9_999(not langchain-core's 25) and how to cap it once a tool
is added — as visible asMAX_TURNS/MAX_REQUESTSon the other templates. -
The conformance probe serves a
content_hashwith every skill body, the way
the platform does, and C13b now requires a model-pulled activation to carry
that hash. Before, no conformance run ever saw askill_hash, and the one
fidelity clause that existed skipped a null silently — an adapter that stopped
stamping versions would have stayed green.
Fixed
-
A refused manifest registration no longer costs the trace. The caller-thread registration
ladder is milliseconds by necessity, which cannot outlast a Cloud Run revision with no
available instance; the trace was then shipped carrying a LOCAL id the platform had never
stored and rejected with400 manifest_id '...' does not exist. Production took 1,315 of
exactly those in the 48 h to 2026-09-04, all from this SDK. Re-registration now happens on
the background sender, where waiting costs the caller nothing: five jittered attempts,
bounded, and the trace is held until an id exists rather than sent under one that does not.
Applies to every adapter that registers a manifest — langchain, the generic
@decimalai.tracepath, ADK, LlamaIndex, OpenAI Agents and the Claude Agent SDK. The
last four had the same defect with no retry ladder at all, in two shapes: two stamped
the local id and took400 manifest_id ... does not exist, two sent no id and took
400 manifest_id is required. Both lose the trace. -
_poll_for_tracein the framework end-to-end tests raisesTraceNeverArrivedinstead of a
bareAssertionErrorwhose message contained "Timed out" — the substring the live-test
helper matches to classify a failure as provider-unavailable and SKIP it. A lost trace was
being reported as a quota skip, the same defect class as the 2026-09-03 journeys finding. -
decimalai initgave up on the first admission abort. A single-instance
backend at its concurrency limit answers HTTP 429 in ~0 ms with no Retry-After
(Cloud Run's "no available instance"); measured on production 2026-09-03 that
was 84-92% of requests in a ten-minute window.initmade one
/api/v1/auth/verifycall — anddecimalai init <agent>one bare
GET /api/v1/agentsand oneGET /api/v1/agents/{name}/skills— and exited on
any non-2xx, so the quickstart failed outright, and the scaffold wrote no
agent.py, for anyone who ran it while the platform was busy (the fleet's
scaffold canary filed those asdecimalai_init_wrote_no_agent_file). All three
calls now retry a 429/502/503/504 twice (0.5 s, then 1.5 s; a short
Retry-Afterwins) before reporting the status. A 401/403 is a real answer and
is never retried. The prompt read was already on the SDK's retry ladder and
still only costs a note in the file, never the file. -
The
openai-agentsscaffold died with a traceback when the model called a
tool the file does not define. The Support pack's starter prompt named
kb_search; a model that called it raised
agents.exceptions.ModelBehaviorError: Tool kb_search not foundout of
Runner.run_sync(the fleet's scaffold canary, 2026-09-04).run()now catches
ModelBehaviorErrorthe way it already caughtMaxTurnsExceededand returns a
message naming the mismatch between the prompt's Tools line and the tools
attached to the Agent. The hermetic J1 journey now replays that class: a second
run of the generated file against a stub that calls an unknown tool must exit 0
without a traceback.