What you get
CrewAI has noagent_config(). It has a skill loader of its own, and decimalai.crewai.skills() points that loader at the folder decimalai skills add writes, so an agent runs on registry skills before you have a DecimalAI account.
With a key, instrument() traces each crew. It can also serve the skills saved on an agent instead, so you can change them without redeploying.
Install
decimalai and CrewAI side by side. The adapter supports crewai 1.15.27 and later, and CrewAI needs a Python below 3.14. Tracing takes two more packages, listed under Add a key.
Run with no account
Save this asmain.py:
decimalai.crewai.skills() raises SkillsNotInstalledError. The program never calls decimalai.init(), so it needs no DECIMAL_API_KEY and sends DecimalAI nothing.
skills=decimalai.crewai.skills()is the installed folder. CrewAI lists every skill in it in its own catalog and gives the agent its ownload_skilltool, which returns a skill’s full text.tools=decimalai.crewai.skill_tools()adds what CrewAI’s loader lacks.load_skill_resourcereads a file under a skill’sreferences/,assets/orscripts/.run_skill_scriptruns one of itsscripts/, with no shell and a 60-second limit. Both accept only installed skills and paths inside them.run_skill_scriptdoesn’t enforce a skill’sallowed-tools, andskill_tools(scripts=False)leaves it out.- CrewAI reads the whole folder. Every skill folder in
.agents/skillsis offered, whether or not.decimal/skills.tomllists it.agent_config()with no key, on other frameworks, uses only the listed ones.
Your own tools
List your tools beforeskill_tools():
Add a registry skill
main.py. The model loads the skill and gives the real command, playwright-cli attach --cdp=http://localhost:9222.
The command wrote the skill’s files to .agents/skills/, listed it in .decimal/skills.toml, and recorded its exact bytes in .decimal/skills.lock. To find others, see Browse the registry. A skill you wrote goes in the same folder.
Add a key
A key alone changes nothing here, becausemain.py never calls decimalai.init(). To keep CrewAI’s loader and record its loads, see Its own skill loader. To serve the skills saved on an agent, use instrument().
Get a key from Settings → API keys, add the tracing packages, and put a skill on the agent. --to-agent creates the agent if it’s new:
skills= and tools= from the agent:
enable_skill_loader=Truehooks CrewAI’sbefore_llm_call. There’s noload_skillon this route, so each model call an agent makes is ranked on the task’s description, and the skill list goes into that call right after CrewAI’s system prompt, with the full text of the skill ranked first. If the ranking wasn’t about this task and the agent has other skills, the call gets the list alone, and the model can’t open a skill from it. Calls outside an agent’s turn, such as output conversion and guardrails, are left alone.decimalai.init()comes first. Without it,instrument()installs and the agent gets no skills, with no error.decimalai.init(crewai=True, agent_name="my-agent")is the one-line form of both calls.- The agent has no
skills=. An agent with CrewAI skills of its own keeps them, and this route stays out of its calls. - Call it before the first
kickoff(). CrewAI copies its hooks into an agent’s executor when it builds one, so an executor built earlier gets no skills. - The two packages are for tracing. Skills reach the model without them, but no run is recorded. Use
openinference-instrumentation-anthropicor-google-genaifor those models. instrument()doesn’t connect the project. It copies nothing from.decimal/skills.tomland writes no.decimal/link.toml, which is why the skill goes on with--to-agentor on the agent’s page. Folders in.agents/skillsgo unused on this route.
Change the prompt without redeploying
CrewAI’s prompt stays in your code. It’s built from therole, goal and backstory you pass to Agent(...), and instrument() reads no saved prompt, so a prompt saved in the dashboard doesn’t reach this agent. Only the skills can change without redeploying: add or remove one on the agent’s Prompt & skills page, and later runs get the new list. {{name}} variables and MissingPromptVariable don’t apply.
To keep the text on DecimalAI anyway, read it yourself with the neutral agent_config() when you build the agent:
support.prompt is the text as saved, with any {{name}} unfilled. It’s read when you call agent_config(), so a new version reaches the next agent built after a fresh call, and its trace records no prompt version. With a key, that call also connects the project.
Conversations
This doesn’t apply:decimalai.crewai has no conversation(), and each kickoff() is one run with its own task and its own trace.
Its own skill loader
This is the route in Run with no account:decimalai.crewai.skills() and skill_tools(). To record its loads, add a key and the tracing packages from Add a key, and put one line at the top of main.py:
- Each load counts as Loaded, with the version of the text the model received, and the names in CrewAI’s catalog count as Offered.
- Updates take effect at once. CrewAI reads a skill’s text from disk on every load, so after
decimalai skills updatethe same agent serves the new version. - DecimalAI’s route steps aside by itself. That flag also turns on the
instrument()route, which leaves an agent withskills=alone, so there’s no need forskills=False. If another agent in the same crew gets skills that way, a warning says once that two catalogs reached the model in that run.
Tracing
instrument() or init(crewai=True) turns tracing on for the process, and each crew run is one trace. CrewAI emits no spans to your tracer provider by itself, so OpenInference’s instrumentors supply them, and each of those is a package you install.
openinference-instrumentation-crewairecords the crew, each task, agent interactions and tool calls, with inputs and outputs.- A provider instrumentor (
openinference-instrumentation-openai,-anthropicor-google-genai) records the model calls, with the model name, token counts and messages. CrewAI’s own instrumentor emits no model call. - Skills on the
instrument()route are recorded as Offered and Delivered, never Loaded, because the model never asks for one. - To trace with no skills, use
decimalai.init(crewai=True, skills=False), or setDECIMALAI_SKILLS=0. instrument(on_trace=fn)callsfnonce per run, failed runs included, with a copy of the finished trace before it’s sent. A run insidedecimalai.start_trace()is filed as that trace’s child.- Several agents in one process. Wrap a kickoff in
agent_run("billing-crew"), fromdecimalai.providers, to file the run and route its skills under that name.
decimalai.flush() sends them at once.
Troubleshooting
- The agent ignored its skill. Have the task ask it to load one, as
main.pydoes. See the measurement in Run with no account. SkillsNotInstalledError. The project has no skills yet. Rundecimalai skills addin its folder.- A skill is missing from CrewAI’s catalog. CrewAI skips a folder it can’t parse, and logs it on
crewai.skillsinstead of raising. Itsmetadataparser requires every value to be a string.decimalai skills verifyreports what a loader would reject. NO CrewAI traces will be captured.openinference-instrumentation-crewaiis missing, or refused your CrewAI version. The warning says which.- The trace has crew and task spans but no model or tokens. The provider instrumentor is missing. It’s only logged at INFO, as
CrewAI traces will lack openai model/token detail. - No skills arrive on the
instrument()route, and nothing is logged. Check fordecimalai.init()before the firstkickoff(), and forskills=on the agent. That one is logged at INFO, once per agent. - LiteLLM calls aren’t traced. DecimalAI turns on the OpenAI, Anthropic and Google instrumentors only. Install
openinference-instrumentation-litellmand callLiteLLMInstrumentor().instrument()yourself. CrewAI ran its before_llm_call hook on a thread with a running asyncio event loop. The deprecatedCrewAgentExecutorunderCrew.akickoff()blocks the loop during ranking. Dropexecutor_class, or useCrew.kickoff_async().enable_load_skill_tool is not supported on the crewai adapter. The argument does nothing, because a hook can’t add a tool. For a model that asks for skills, use its own skill loader.