Repository navigation
v0.20.0
Changed (breaking): Google ADK agents get their prompt and skills from load_agent()
- New:
decimalai.adk.load_agent(name, fallback=..., on_unavailable="continue")returns
instruction, an ADK instruction provider forLlmAgent(instruction=...): the agent's saved
prompt ({{placeholders}}filled from the session's state), then the skill list routed on the
invocation's message. Itstoolsisload_skill, limited to the agent's skills: ADK agents
can fetch a skill's text mid-turn for the first time. Each invocation is routed once, on its
own message, the way OpenAI Agents runs are. Built only on ADK's public instruction and tool
APIs. DecimalaiPlugin()goes inApp(plugins=[...]), ADK's own place for plugins. An invocation
whose agent hasload_agent()'s instruction is one trace filed under that DecimalAI agent,
with its prompt version, placeholder names and the skills offered, loaded and delivered.
load_skill's results are in the trace's model inputs.- Removed:
decimalai.adk.instrument(),init(adk=True)and theRunner.__init__patch
behind both, which added the plugin to every runner in the process; the plugin's skill
injection (a menu and a body pasted intosystem_instruction); and itsenable_skill_loader
andenable_load_skill_toolparameters.DECIMAL_AUTO_TRACE=adknow logs a warning that
says to add the plugin, and traces nothing. - An agent that carries ADK's own
SkillToolset, or another tool namedload_skill, gets no
DecimalAI skills, with one warning. decimalai init --framework adkwrites the new shape.
Migration:
# before
decimalai.init(adk=True, agent_name="support")
agent = LlmAgent(name="support", model=MODEL, instruction=BASE, tools=[lookup_order])
runner = InMemoryRunner(agent=agent)
# after
from decimalai.adk import DecimalaiPlugin, load_agent
support = load_agent("support", fallback=BASE)
agent = LlmAgent(name="support", model=MODEL, instruction=support.instruction,
tools=[lookup_order, *support.tools])
runner = InMemoryRunner(app=App(name="support", root_agent=agent, plugins=[DecimalaiPlugin()]))Fixed: OpenAI Agents traces record OpenAI's cached input tokens
- Each model call's
cache_read_tokensnow carries the cached-input count OpenAI reports
(usage.input_tokens_details.cached_tokens), so the trace'stotal_cache_read_tokensis no
longer always null. It is a subset ofinput_tokens, as OpenAI counts it. - On the Responses API (the default model) a reported 0 is recorded as 0, a measured cache miss.
On chat-completions models, LiteLLM, and streamed responses only the span's usage is available,
andopenai-agentswrites 0 there when the provider reported nothing; those record a positive
count only, and leave 0 as not reported.
Changed: a failed skill route serves the agent's menu instead of no skills
- When
POST /api/v1/skills/routetimes out or fails with a 500 or 504, the SDK asks once for the
agent's own menu (GET /api/v1/skills/menu) and the turn gets the agent's skills, unranked,
instead of none. Before, the agent answered without skills and only the trace showed it. This
covers every adapter that routes throughSkillRouter.build_prompt_fragment, including
load_agent(). - The extra request has its own 2 s read budget and does not wait out a
Retry-After, so a failed
route costs a turn at most 2 s more. It is not made after a 429 or 503 (the platform is shedding
load), a connection failure, or while the circuit breaker is open. - After a fallback, routes from the same host and API key are skipped for 30 s and turns go
straight to the menu, so they do not each wait out the route's timeout again. routing_status().menu_fallbackscounts the turns served this way. They had their skills, so
they do not makehealthyFalse; a rising count says routing itself is failing.