Skip to main content

Upgrade from any older release

You don’t step through the releases. Go straight to the current SDK and change each old call once:
  1. Install it on every machine and CI job: pip install -U "decimalai[langchain]>=0.27", with your framework’s extra in place of langchain.
  2. Build each agent from agent_config(), as the table below shows. Your old prompt text becomes fallback=: the prompt saved in the dashboard takes its place, and the fallback runs while none is saved.
  3. Run your code. An old call raises an error, usually naming what replaces it, so a spot you missed shows up the first time that code runs. A few changes raise nothing.
  4. Write generated files again. A file decimalai init wrote on an older release can import names that are gone. decimalai init <agent-name> --force --framework <framework> overwrites it, your edits included.
  5. Migrate installed skills, if .decimal/skills.lock is a version 1 lock or you have an npx lock: run decimalai skills migrate once.
In each, support = agent_config("support-agent", fallback=YOUR_PROMPT). CrewAI has no agent_config(): decimalai.crewai.instrument(enable_skill_loader=True) stays its route. Each framework’s page has the whole program. The sections below show each release’s own code, so the oldest say load_agent(), which 0.21 renamed agent_config().

Changes that raise no error

  • Flags that trace only. init(openai_agents=True) (from 0.18) and init(langchain=True) (from 0.25), and DECIMAL_AUTO_TRACE set to either, give an agent no prompt or skills. A LangChain run with no agent_config() middleware says so once, in a warning. DECIMAL_AUTO_TRACE=adk (from 0.20) logs a warning and traces nothing.
  • prompt_source’s values changed in 0.21 (see that section), and 0.24 added "fallback (no key)".
  • A misspelled agent name makes a new agent (from 0.24). Before, agent_config() raised AgentNotFoundError.
  • With no key, agent_config() uses only the skills .decimal/skills.toml lists and sends nothing (from 0.25). 0.24 searched the public registry with each message and added what the model loaded, and 0.21 to 0.23 needed a key.
  • A skill the SDK creates reaches only the agents you add it to (from 0.25.1). Through 0.25.0 a create that said nothing was offered to every agent. Pass agent_name= (decimalai skills sync --to-agent NAME), or offer_scope="workspace".
  • decimalai skills sync (from 0.25): when your file and DecimalAI’s copy both changed, DecimalAI’s copy wins and yours is kept in .decimal/backup/. Older releases let the newer edit win and kept no copy.
  • One agent name reaches every call (from 0.17). Through 0.16, init(agent_name=...) reached only the adapters a flag on the same init() call installed. An instrument() you called yourself, start_trace() and SkillRouter each needed the name again, and a call that left it out filed its traces under another agent and was offered none of the agent’s skills, with no error. SkillRouter() needed api_key= as well.

Moving to SDK 0.25

0.25 changes one module, decimalai.langchain: a LangChain agent gets its prompt and skills from agent_config(), as one middleware you pass to your own create_agent(...), and nothing in LangChain is patched. Through 0.24, instrument(enable_skill_loader=True), and decimalai.init(langchain=True) with it, patched BaseChatModel.invoke, ainvoke, stream and astream and pasted the routed skills into every chat-model call in the process. Code written for 0.24 fails loudly where it passed the loader’s arguments: instrument() raises a TypeError for enable_skill_loader, enable_load_skill_tool, skill_body_top_k, priority_skills and runtime_policy. The one change with no error is init(langchain=True), which now traces only; the first traced run with no agent_config() middleware says so in a warning, and init(langchain=True, skills=False) silences it. CallbackHandler is unchanged. Install the extra again, pip install "decimalai[langchain]", which now brings langchain (where create_agent lives) beside langchain-core. decimalai init <agent-name> --framework langchain writes a file in the new shape. Threads are in Conversations. Files decimalai init wrote through 0.24.1 open with decimalai.init(agent_name=AGENT_NAME) and raise DecimalConfigError with no key. A file written now calls no init(), so it also runs with no key.

Your own OpenAI or Gemini calls

0.25 adds decimalai.openai and decimalai.google_genai, with nothing you must move. Through 0.24, code that called the OpenAI SDK itself used the top-level decimalai.agent_config(): it wrapped run.tool_spec in OpenAI’s tool shape itself, answered load_skill with run.load_skill(name), and needed decimalai.init(openai=True), agent_run() and the instrumentor package for a run to reach a trace. That still works. decimalai.openai.agent_config() does the same in OpenAI’s shapes, and traces each run with no other line:
Gemini code can switch the same way, to decimalai.google_genai.agent_config().

Two changes that need no code

decimalai.pydantic_ai’s capability traces its own runs, so the decimalai.init(otel=True) and Agent.instrument_all() lines a Pydantic AI file carried can go (they keep working, and nothing is reported twice; Tracing). An OpenAI Agents chat on Claude keeps its first run’s instructions once its runs share a RunConfig(group_id=...) (Claude through LiteLLM).

Moving to SDK 0.23

0.23 changes one module, decimalai.anthropic: Anthropic Messages API agents get their prompt and skills from agent_config(), one run per user message, and nothing in the Anthropic SDK is patched. Through 0.22, instrument(enable_skill_loader=True) patched Messages.create(), .stream() and .parse(), sync and async, for every Anthropic client in the process, putting a skill menu, and sometimes one skill’s text, into each request’s system. Code written for 0.22 fails loudly: instrument() is now a stub that raises a TypeError naming agent_config(), and skill_system() and get_current_routing_id() are removed.
Install the new extra, pip install "decimalai[anthropic]", which brings the tracing library agent_config() uses, and set up any OpenTelemetry tracing of your own before the first agent_config(). decimalai init <agent-name> --framework anthropic writes a file in the new shape. Chats are in Conversations.

Moving to SDK 0.21

0.21 renames three things: load_agent() is agent_config(), Google ADK’s DecimalaiPlugin is DecimalAIPlugin, and code that calls a model itself starts a run per message. Code written for 0.20 fails loudly: load_agent() and DecimalaiPlugin() raise a TypeError naming the new function, and support.system, support.tool_spec and support.load_skill raise an AttributeError saying where each went. The one change with no error is the value of prompt_source. The arguments are the same, and so is what each config holds: instructions and tools on the OpenAI Agents SDK, the capability on Pydantic AI, instruction and tools on Google ADK. A run serves its own load_skill calls from any thread or task; in 0.19 and 0.20 a load was served against the latest system() of the thread or task that called it. See Your own model calls. Files decimalai init wrote before 0.21 import load_agent and fail: write them again, or rename the import and the call by hand.

Moving to SDK 0.20

0.20 gives Google ADK its own load_agent() and removes the process-wide install it replaces. Code written for 0.19 fails loudly, with an ImportError or AttributeError for decimalai.adk.instrument, or a TypeError for init(adk=True) and for DecimalaiPlugin(enable_skill_loader=...) or enable_load_skill_tool=. The one silent case is DECIMAL_AUTO_TRACE=adk, which logs a warning naming the plugin and traces nothing.

Google ADK: load_agent() and the plugin in the App

Through 0.19, decimalai.init(adk=True) and decimalai.adk.instrument(enable_skill_loader=True) patched Runner.__init__ to add the DecimalAI plugin to every runner in the process, and the plugin pasted a skill menu and a skill’s text into each request’s system_instruction. 0.20 removed both. An agent gets its prompt and skills from load_agent(), which you pass into your own LlmAgent(...), and its traces come from DecimalaiPlugin() in its App(plugins=[...]):
  • Traces come only from the plugin in the App. A runner built without it is not traced, and nothing else in the process is touched. DecimalaiPlugin(agent_name=..., parent_trace_id=..., on_trace=...) takes the arguments it took before, without the two skill ones.
  • Your instruction= text becomes the fallback=. A saved prompt’s placeholders are {{var}}, filled from the session’s state, where a string instruction’s {var} were ADK’s.
  • Skills arrive through load_skill. The model fetches a listed skill’s text when it needs it, and the trace records the skill as loaded. Through 0.19 one body was pasted into the instruction; with DECIMALAI_LOAD_SKILL_TOOL=0 that still happens, through load_agent().
  • ADK’s own SkillToolset needs only the plugin in the App to have its loads recorded as activations.
See Google ADK for what the config holds. Files decimalai init --framework adk wrote before 0.20 import instrument and fail: write them again, or make the change above by hand.

Moving to SDK 0.19

0.19 changes what two load_agent() calls give you: the Pydantic AI one, which replaces decimalai.pydantic_ai.instrument(), and the top-level decimalai.load_agent(). Code written for 0.18 fails loudly, with an ImportError or AttributeError for instrument and get_current_routing_id, an AttributeError for config.system_prompt and the other removed fields, or a TypeError for version= and cache_ttl_seconds=.

Pydantic AI: load_agent()

Through 0.18, decimalai.pydantic_ai.instrument(enable_skill_loader=True) gave every Agent in the process skills and a load_skill tool by patching Pydantic AI, and opened a run span around every run. 0.19 removed it, and an agent gets its prompt and skills from load_agent(), a capability you pass in Agent(capabilities=[...]):
  • Traces no longer come from instrument(). From 0.19 to 0.24 use decimalai.init(otel=True) with Agent.instrument_all(), or a provider flag such as decimalai.init(openai=True): one, not both. From 0.25 the capability traces its own runs. The Pydantic AI harness’s decimalai.pydantic_ai_harness.skills() needs no instrument() either.
  • Your system_prompt= text becomes the fallback=.
  • The agent’s name. The capability routes as the name it was loaded with, whatever the Agent is called. Through 0.18, Agent(name=...) won.
  • Another tool named load_skill now fails the run with Pydantic AI’s own error. Through 0.18, DecimalAI’s was renamed decimalai_load_skill; rename yours instead.
  • get_current_routing_id() was removed with instrument(). Each run’s routing decision is recorded on its trace.
See Pydantic AI for what the capability holds.

Your own model calls: decimalai.load_agent()

Through 0.18, decimalai.load_agent() returned the saved prompt alone. In 0.19 it returns the agent’s prompt and skills, for code that calls a model itself: support.system(message, context=...), support.tool_spec and support.load_skill(name), which 0.21 moved onto a run. Code that wants only the prompt text reads support.prompt:
Files decimalai init wrote before 0.19 read config.system_prompt, and so does a Support project from decimalai init --project. Rename config to support and config.system_prompt to support.prompt: a Support project’s checks read support. An agent file can be written again instead.

Moving to SDK 0.18

0.18 removes what earlier releases kept only for compatibility. A removed name fails loudly, with an ImportError, AttributeError or TypeError.

OpenAI Agents SDK: load_agent()

Through 0.17, instrument(enable_skill_loader=True) and init(openai_agents=True) gave every agent in the process skills by patching the Agents SDK. In 0.18 both trace only (enable_skill_loader is no longer an argument of instrument()), and an agent gets its prompt and skills from load_agent():
See OpenAI Agents SDK for what instructions and tools hold.

Removed names

decimalai init --project <dir>, which writes a Support project, is a different option and is unchanged.

A project SDK 0.14 installed

The version 1 lock fallback is gone as well: router.export() and router.update_skills() refuse a project whose .decimal/skills.lock decimalai 0.14 wrote, as every decimalai skills command already did. Run decimalai skills migrate once, as the next section describes.

Upgrading the SDK: skills on disk

SDK 0.15.0 installs registry skills like packages: a manifest, .decimal/skills.toml, a version 2 lock that records every byte written, and one root, .agents/skills/. A project set up by SDK 0.14 or older has a version 1 .decimal/skills.lock (or the npx installer’s .decimal/skills.lock.json), which says which skills were installed but not which bytes. The SDK refuses to work from it, and every command says so:
install, install --frozen and verify exit 3; status reports it. Nothing converts the lock implicitly.

Run it once

1

Upgrade everyone on the project

Do it for every machine and CI job that installs skills in this project. A 0.14 decimalai skills export, run after the migration, merges version 1 entries into the new lock: install --frozen then refuses it (exit 3), and skills install drops those entries and leaves their folders as unmanaged.
2

Migrate

It needs the registry, and for your own or linked skills an API key of the organization that installed them (DECIMAL_API_KEY); public skills migrate without one. If an entry does not resolve, nothing changes and it exits 7, naming it. decimalai skills migrate --yes migrates the others.
3

Review and commit

.decimal/migrated-v1/ is gitignored. In CI, replace the old export step with decimalai skills install --frozen.

What it does

  1. Seeds .decimal/skills.toml from the old lock. Version 1 entries become "latest", because those locks did not record real versions. Npx entries keep the exact version npx installed. If the manifest already exists, it wins: none of its lines changes.
  2. Resolves every entry again, by skill id first and by name when the registry no longer knows the id. An entry whose name now resolves to a different skill than its recorded id is skipped and reported. The trust gate applies without its question: a Blocked skill is refused, a Withheld one too unless your organization owns or uses it, and a Caution or not-yet-reviewed one installs with a warning.
  3. Installs each skill fresh from the registry. The old hashes are never trusted, so every folder is written again in the new format.
  4. Moves old folders, and deletes nothing. A folder inside .agents/skills/ goes to .decimal/migrated-v1/<txid>/skills/<folder>, so a stale copy cannot load beside the new one. A folder anywhere else (.claude/skills/, .continue/skills/, …) stays and is listed, since an interactive agent may still read it: delete it yourself once nothing does. A folder for an entry that did not resolve, or was skipped, stays as one the engine never touches.
  5. Keeps the old locks in the same .decimal/migrated-v1/<txid>/, removes the originals, writes the version 2 lock and .agents/.claude-plugin/plugin.json, and prints each skill, what the old lock claimed, the version installed, and where its old folders went.
A second run finds no old lock and does nothing. A run that stops partway (a crash, Ctrl-C) leaves every old file in its place or in the backup folder, and the next run picks it up.

After the migration

  • Skills from a version 1 lock start at latest. Pin one with decimalai skills update <name>@<N>; the old lock’s version numbers were not real.
  • Point your framework at .agents/skills. One root serves every runtime: decimalai.skills_dir() for the native loaders, claude --plugin-dir "$(git rev-parse --show-toplevel)/.agents" for Claude Code. The --agent and --scope global flags are gone.
  • Replace the old verbs: skills export <ref> and skills install <ref> are skills add <ref>; SkillRouter.pull_missing() is skills install. 0.18 removed the old verbs; Removed names lists what replaces each.
  • skills pull changed too. Through 0.14 it wrote ./<url_slug>/SKILL.md with a frontmatter of its own, name and description only, and overwrote an existing folder without asking.
  • The adapters no longer write skills to disk. Through 0.14, an adapter could mirror your organization’s skills into the working directory in the background. In 0.15, disk changes only when a decimalai skills command runs.