agent_config() reads an agent’s prompt and skills from DecimalAI and hands them over per user message, as a run: run.system (the saved prompt, then the agent’s skill list) for system_instruction, run.message (the user turn) and load_skill, as a Python function for automatic function calling (run.tools) or as a function declaration for a loop of your own (run.tool_params). Each run is one trace, filed under the DecimalAI agent. Nothing in the google-genai SDK is patched. decimalai.google_genai needs SDK 0.25 or later; through 0.24, code that called Gemini itself used decimalai.agent_config().
Building on Google ADK (LlmAgent) instead? See Google ADK.
Install
google-genai and openinference-instrumentation-google-genai, which agent_config() uses to trace its runs. genai.Client() reads GOOGLE_API_KEY (or GEMINI_API_KEY).
Use
agent_config("support-agent")reads the agent’s saved prompt when it is called. It initializes the SDK fromDECIMAL_API_KEYwhendecimalai.init()has not been called, and a name your workspace has no agent by is created, so a misspelled name makes a new agent rather than an error.fallback=is what runs when the agent has no saved prompt yet, when no DecimalAI key is set, or when DecimalAI cannot be reached at startup. With no key at all, the agent runs without a DecimalAI key: the skills your project lists in.decimal/skills.toml, with nothing sent.support.run(question)routes the agent’s skill list onquestionand opens the run’s trace. It calls no model: make the model calls inside thewithblock.run.systemis the system instruction: the saved prompt, then the agent’s skill list with one sentence telling the model to load a skill before using it.run.messageis the user turn, as text. Send it instead of the bare question: in a chat it can carry more.run.toolsholdsload_skillas a Python function, which automatic function calling declares and calls like your own. The model calls it with a skill’s name and gets the skill’s full text back, which counts as delivered and activated on the usage ladder. Its parameter is a plain string: when the agent’s whole list fits, a name not on it is answered with the list and loads nothing.
generate_content.
Your own loop
Automatic function calling raisesKeyError when the model asks for a function you did not pass, for example one your saved prompt names. A loop of your own can answer that call instead, and decimalai init --framework google-genai writes one. It takes run.tool_params (the same load_skill as a function declaration, whose parameter is limited to the listed skills) and answers each call with run.tool_result(call), which returns the function_response part for load_skill and None for any other function:
error key, as text the model can read. run.load_skill(name) returns the text alone, for a dispatcher of your own.
Async
Open the run withasync with support.run(question) as run: for client.aio: run.tools then holds an async function, and await run.atool_result(call) (await run.aload_skill(name) for the text alone) keeps a load off the event loop.
Chats
A chat keeps one conversation, and a conversation’s system instruction andload_skill stay what its first message got. A newly saved prompt or a newly assigned skill reaches the next conversation, not an open one.
run.messageis the user turn to send: the question, plus, for an agent whose skill list is cut to fit, the skills routed for this message that the chat has not shown yet.conversation.stateis the conversation as JSON-ready data. A server that keeps no chat in memory stores it beside the chat’s history, andsupport.conversation(state=saved)resumes it in another process.- Variables are the conversation’s: they are filled once, at its first message.
Change the prompt without redeploying
agent_config() keeps a local copy of the prompt and re-reads it in the background at most once a minute, so a version saved in the dashboard reaches the next run within a minute, with no redeploy. A saved prompt’s variables, written {{name}}, are filled from support.run(question, variables=...); a variable with no value stops the run before any model call, with a MissingPromptVariable error that names it.
When an agent’s skills are switched off
- The tool’s kill switch. With
DECIMALAI_LOAD_SKILL_TOOL=0ordecimalai.init(load_skill_tool=False), every run is routed and the text of the skills picked for it goes intorun.systeminstead, andrun.toolsandrun.tool_paramsare empty. decimalai.init(enabled=False)afteragent_config()stops routing and skills for that config; the prompt it read keeps running.on_unavailable="fail". By default a run whose skill list never came back answers without skills, and its trace says so. Withagent_config(..., on_unavailable="fail")opening the run raises instead.
Tracing
agent_config() turns on Gemini tracing (OpenInference’s instrumentor, which wraps the SDK’s classes for the process) on the same pipeline as decimalai.init(google=True), and sends only its runs: each run is one trace, filed under support.name, with its model calls, the prompt version, the variable names it filled, and the skills offered, loaded and delivered. A Gemini call made outside a run is held back, and so are the app’s own spans; decimalai.init(google=True) sends every Gemini call. Set up your own OpenTelemetry tracer provider, and decimalai.init(otel=True), before the first agent_config(). agent_config(..., on_trace=fn) calls fn once per run with a copy of the finished trace.
Checkpoint: run the agent from Use once with a question that matches one of your skills, then
print(support). It names the prompt version the agent ran and the skills on its list, for example GeminiAgentConfig(name='support-agent', prompt_version=3, skills=['refund-policy']), and the run appears on the Traces page under that name. No trace? Check that the model calls were made inside the with block.What’s next
OpenAI SDK
The same run for your own OpenAI Chat Completions or Responses API loop.
Google ADK
The same prompt and skills for an agent built on Google ADK.