Install any skill in seconds. Free to start, no credit card required.
Get Started Free →ToolUniverse plugin router. STEP 1 BEFORE ANY ANALYSIS: if the data folder contains `*_executed.ipynb`, run `tu run read_executed_notebook '{\"data_folder\":\"<path>\",\"search\":\"<keyword>\"}'` to extract its cell outputs and apply EVERY filter/sample-exclusion the notebook used — even when the question says 'Using DESeq2/Run X/Compute Y' (this describes the METHOD the notebook used, not a request to rerun). The notebook's cell outputs are the only published authoritative answers; reimplementi
3/3 safety checks passed
4 of 22 test cases passed with the skill.
Lift withheld: 4 comparable cases; this report requires 8.
This benchmark measured an earlier version of the skill.
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add tooluniverse
claude --plugin-dir "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents"The same install from Python, for a notebook or a setup script.
pip install "decimalai>=0.15"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
print("Added. Start Claude Code with the command below.")claude --plugin-dir "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents"Type these in a Claude Code session. No account or API key. It writes the skill and any files it bundles, and asks first when its safety rating isn't Passed.
/plugin marketplace add decimal-labs/decimalai-claude-plugins
/plugin install decimalai@decimalai/decimalai:install tooluniverseThe plugin needs python3 and curl on your machine.
No Python or account. Claude Code picks it up in its next session.
curl -fsSL --create-dirs -o .claude/skills/tooluniverse/SKILL.md https://app.decimal.ai/s/tooluniverse/SKILL.md.claude/skills/tooluniverse/SKILL.mdThis gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[claude-agent-sdk]"
decimalai skills add tooluniverseimport asyncio
from claude_agent_sdk import ClaudeAgentOptions
from decimalai.claude_agent_sdk import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
async def main():
question = "Hello!"
async with support.run(question) as run: # one user message, one run
async for message in run.query(options=ClaudeAgentOptions(max_turns=6)):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())Prefer its own loader? ClaudeAgentOptions(plugins=[skills_plugin()], skills="all") reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[claude-agent-sdk]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
import asyncio
from claude_agent_sdk import ClaudeAgentOptions
from decimalai.claude_agent_sdk import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
async def main():
question = "Hello!"
async with support.run(question) as run: # one user message, one run
async for message in run.query(options=ClaudeAgentOptions(max_turns=6)):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())Prefer its own loader? ClaudeAgentOptions(plugins=[skills_plugin()], skills="all") reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
options = ClaudeAgentOptions(system_prompt=f"You are a helpful agent.\n\n{skill}", max_turns=6)
async def main():
async for message in query(prompt="Hello!", options=options):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai-agents]"
decimalai skills add tooluniversefrom agents import Agent, Runner
from decimalai.openai_agents import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
name=support.name,
instructions=support.instructions, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")Using SandboxAgent? capabilities=[Shell(), decimalai.openai_agents.sandbox_skills()] points its own loader at the same folder.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai-agents]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
from agents import Agent, Runner
from decimalai.openai_agents import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
name=support.name,
instructions=support.instructions, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")Using SandboxAgent? capabilities=[Shell(), decimalai.openai_agents.sandbox_skills()] points its own loader at the same folder.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = Agent(name="support", instructions=f"You are a helpful agent.\n\n{skill}")
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai]"
decimalai skills add tooluniverseimport json
from openai import OpenAI
from decimalai.openai import agent_config
client = OpenAI()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your tools, as Chat Completions takes them, and what answers each.
TOOLS = [{"type": "function", "function": {
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
# run.system is your prompt, then the skill list.
messages = [{"role": "system", "content": run.system}, run.message]
while True:
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=messages,
tools=[*TOOLS, *run.tools], # your tools, then load_skill
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
break
for call in reply.tool_calls:
# load_skill is answered by the run; your own tools by FUNCTIONS.
function = FUNCTIONS.get(call.function.name)
messages.append(run.tool_result(call) or {
"role": "tool", "tool_call_id": call.id,
"content": function(**json.loads(call.function.arguments)) if function
else f"There is no tool named {call.function.name!r}.",
})
print(reply.content)
# The Responses API takes run.response_tools instead of run.tools.The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
import json
from openai import OpenAI
from decimalai.openai import agent_config
client = OpenAI()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your tools, as Chat Completions takes them, and what answers each.
TOOLS = [{"type": "function", "function": {
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
# run.system is your prompt, then the skill list.
messages = [{"role": "system", "content": run.system}, run.message]
while True:
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=messages,
tools=[*TOOLS, *run.tools], # your tools, then load_skill
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
break
for call in reply.tool_calls:
# load_skill is answered by the run; your own tools by FUNCTIONS.
function = FUNCTIONS.get(call.function.name)
messages.append(run.tool_result(call) or {
"role": "tool", "tool_call_id": call.id,
"content": function(**json.loads(call.function.arguments)) if function
else f"There is no tool named {call.function.name!r}.",
})
print(reply.content)
# The Responses API takes run.response_tools instead of run.tools.No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=[
{"role": "system", "content": f"You are a helpful agent.\n\n{skill}"},
{"role": "user", "content": "Hello!"},
],
).choices[0].messageThis gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[anthropic]"
decimalai skills add tooluniverseimport anthropic
from decimalai.anthropic import agent_config
client = anthropic.Anthropic()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
question = "Hello!"
with support.run(question) as run: # one user message, one run
answer = client.beta.messages.tool_runner(
model="claude-haiku-5-5",
max_tokens=4096,
system=run.system, # your prompt, then the skill list
tools=[*run.tools], # your tools, then load_skill
messages=[{"role": "user", "content": question}],
).until_done()The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[anthropic]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
import anthropic
from decimalai.anthropic import agent_config
client = anthropic.Anthropic()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
question = "Hello!"
with support.run(question) as run: # one user message, one run
answer = client.beta.messages.tool_runner(
model="claude-haiku-5-5",
max_tokens=4096,
system=run.system, # your prompt, then the skill list
tools=[*run.tools], # your tools, then load_skill
messages=[{"role": "user", "content": question}],
).until_done()No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
reply = client.messages.create(
model="claude-haiku-5-5",
max_tokens=4096,
system=f"You are a helpful agent.\n\n{skill}",
messages=[{"role": "user", "content": "Hello!"}],
)This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[google-genai]"
decimalai skills add tooluniversefrom google import genai
from google.genai import types
from decimalai.google_genai import agent_config
client = genai.Client()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your functions, as declarations for the model, and what answers each.
TOOLS = [{"function_declarations": [{
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters_json_schema": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
config = types.GenerateContentConfig(
system_instruction=run.system, # your prompt, then the skill list
tools=[*TOOLS, *run.tool_params], # your functions, then load_skill
)
contents = [{"role": "user", "parts": [{"text": run.message}]}]
while True:
response = client.models.generate_content(
model="gemini-3.5-flash", contents=contents, config=config,
)
if not response.function_calls:
break
contents.append(response.candidates[0].content)
parts = []
for call in response.function_calls:
# load_skill is answered by the run; your own functions by FUNCTIONS.
# A loop of your own rather than automatic function calling, which
# raises KeyError when the model asks for a function you did not pass.
function = FUNCTIONS.get(call.name)
parts.append(run.tool_result(call) or {"function_response": {
"name": call.name, "id": call.id,
"response": {"result": function(**(call.args or {})) if function
else f"There is no function named {call.name!r}."},
}})
contents.append({"role": "user", "parts": parts})
print(response.text)The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[google-genai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
from google import genai
from google.genai import types
from decimalai.google_genai import agent_config
client = genai.Client()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your functions, as declarations for the model, and what answers each.
TOOLS = [{"function_declarations": [{
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters_json_schema": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
config = types.GenerateContentConfig(
system_instruction=run.system, # your prompt, then the skill list
tools=[*TOOLS, *run.tool_params], # your functions, then load_skill
)
contents = [{"role": "user", "parts": [{"text": run.message}]}]
while True:
response = client.models.generate_content(
model="gemini-3.5-flash", contents=contents, config=config,
)
if not response.function_calls:
break
contents.append(response.candidates[0].content)
parts = []
for call in response.function_calls:
# load_skill is answered by the run; your own functions by FUNCTIONS.
# A loop of your own rather than automatic function calling, which
# raises KeyError when the model asks for a function you did not pass.
function = FUNCTIONS.get(call.name)
parts.append(run.tool_result(call) or {"function_response": {
"name": call.name, "id": call.id,
"response": {"result": function(**(call.args or {})) if function
else f"There is no function named {call.name!r}."},
}})
contents.append({"role": "user", "parts": parts})
print(response.text)No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
response = client.models.generate_content(
model="gemini-3.5-flash",
contents="Hello!",
config=types.GenerateContentConfig(system_instruction=f"You are a helpful agent.\n\n{skill}"),
)This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[langchain]" langchain-openai
decimalai skills add tooluniversefrom langchain.agents import create_agent
from decimalai.langchain import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = create_agent(
"openai:gpt-5.4-mini",
tools=[], # your tools; the middleware adds load_skill
middleware=[support.middleware], # your prompt, the skill list and load_skill
)
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[langchain]" langchain-openaifrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
from langchain.agents import create_agent
from decimalai.langchain import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = create_agent(
"openai:gpt-5.4-mini",
tools=[], # your tools; the middleware adds load_skill
middleware=[support.middleware], # your prompt, the skill list and load_skill
)
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = create_agent("openai:gpt-5.4-mini", tools=[], system_prompt=f"You are a helpful agent.\n\n{skill}")
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})This gets SKILL.md only. The skill's 1 other file is not included.
CrewAI's own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" "crewai>=1.15.27"
decimalai skills add tooluniverseimport decimalai.crewai
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=decimalai.crewai.skills(), # the installed folder
tools=decimalai.crewai.skill_tools(), # reads a skill's files, runs its scripts
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()The same install from Python, for a notebook or a setup script. CrewAI's own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" "crewai>=1.15.27"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
import decimalai.crewai
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=decimalai.crewai.skills(), # the installed folder
tools=decimalai.crewai.skill_tools(), # reads a skill's files, runs its scripts
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()No DecimalAI package. CrewAI's own loader reads the folder, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=[Path(".agents/skills")],
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[adk]"
decimalai skills add tooluniversefrom decimalai.adk import DecimalAIPlugin, agent_config
from google.adk.agents import LlmAgent
from google.adk.apps import App
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = LlmAgent(
name="support", # ADK needs a Python identifier
model="gemini-3.5-flash",
instruction=support.instruction, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# DecimalAIPlugin makes each invocation of runners built from this App one trace.
app = App(name="support", root_agent=agent, plugins=[DecimalAIPlugin()])Prefer ADK's own loader? SkillToolset(skills=decimalai.adk.skills(), ...) reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[adk]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
from decimalai.adk import DecimalAIPlugin, agent_config
from google.adk.agents import LlmAgent
from google.adk.apps import App
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = LlmAgent(
name="support", # ADK needs a Python identifier
model="gemini-3.5-flash",
instruction=support.instruction, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# DecimalAIPlugin makes each invocation of runners built from this App one trace.
app = App(name="support", root_agent=agent, plugins=[DecimalAIPlugin()])Prefer ADK's own loader? SkillToolset(skills=decimalai.adk.skills(), ...) reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = LlmAgent(
name="support",
model="gemini-3.5-flash",
instruction=lambda context: f"You are a helpful agent.\n\n{skill}",
)This gets SKILL.md only. The skill's 1 other file is not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[pydantic-ai]"
decimalai skills add tooluniversefrom pydantic_ai import Agent
from decimalai.pydantic_ai import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
"openai:gpt-4o-mini",
name=support.name,
tools=[], # your tools; the capability adds load_skill
capabilities=[support], # your prompt, the skill list and load_skill
)
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")On the Pydantic AI harness, decimalai.pydantic_ai_harness.skills(project) uses its own loader instead.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[pydantic-ai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
from pydantic_ai import Agent
from decimalai.pydantic_ai import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
"openai:gpt-4o-mini",
name=support.name,
tools=[], # your tools; the capability adds load_skill
capabilities=[support], # your prompt, the skill list and load_skill
)
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")On the Pydantic AI harness, decimalai.pydantic_ai_harness.skills(project) uses its own loader instead.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = Agent("openai:gpt-4o-mini", instructions=f"You are a helpful agent.\n\n{skill}")
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")This gets SKILL.md only. The skill's 1 other file is not included.
Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagents
decimalai skills add tooluniverseimport decimalai.deepagents
from deepagents import create_deep_agent
agent = create_deep_agent(model=model, **decimalai.deepagents.skills())
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The default backend reads files but has no shell. To run a skill's scripts, pass skills(backend=LocalShellBackend(...)).
The same install from Python, for a notebook or a setup script. Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagentsfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
import decimalai.deepagents
from deepagents import create_deep_agent
agent = create_deep_agent(model=model, **decimalai.deepagents.skills())
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The default backend reads files but has no shell. To run a skill's scripts, pass skills(backend=LocalShellBackend(...)).
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = create_deep_agent(model=model, system_prompt=f"You are a helpful agent.\n\n{skill}")
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})This gets SKILL.md only. The skill's 1 other file is not included.
Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-framework
decimalai skills add tooluniverseimport asyncio
from agent_framework import Agent
from decimalai.agent_framework import skills
agent = Agent(client=client, instructions="You are a helpful agent.", context_providers=[skills()])
asyncio.run(agent.run("Hello!"))It caches skills by default, so restart the process after decimalai skills update.
The same install from Python, for a notebook or a setup script. Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-frameworkfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
import asyncio
from agent_framework import Agent
from decimalai.agent_framework import skills
agent = Agent(client=client, instructions="You are a helpful agent.", context_providers=[skills()])
asyncio.run(agent.run("Hello!"))It caches skills by default, so restart the process after decimalai skills update.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = Agent(client=client, instructions=f"You are a helpful agent.\n\n{skill}")
asyncio.run(agent.run("Hello!"))This gets SKILL.md only. The skill's 1 other file is not included.
Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agents
decimalai skills add tooluniversefrom decimalai.strands import skills
from strands import Agent
from strands.vended_tools import file_editor, shell
agent = Agent(
model=model, # always pass one: the default is Amazon Bedrock
system_prompt="You are a helpful agent.",
tools=[file_editor, shell],
plugins=[skills()],
)
agent("Hello!")Strands loads an agent's skills once, so build the agent again after decimalai skills update.
The same install from Python, for a notebook or a setup script. Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agentsfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("tooluniverse")
if result.exit_code:
raise SystemExit(result.problems)
from decimalai.strands import skills
from strands import Agent
from strands.vended_tools import file_editor, shell
agent = Agent(
model=model, # always pass one: the default is Amazon Bedrock
system_prompt="You are a helpful agent.",
tools=[file_editor, shell],
plugins=[skills()],
)
agent("Hello!")Strands loads an agent's skills once, so build the agent again after decimalai skills update.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/tooluniverse/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/tooluniverse/SKILL.md").read_text()
agent = Agent(model=model, system_prompt=f"You are a helpful agent.\n\n{skill}")
agent("Hello!")This gets SKILL.md only. The skill's 1 other file is not included.
Adds every file the skill has, pinned so you can update it. Cursor, Copilot, Cline and Warp read this folder by themselves.
pip install "decimalai>=0.15"
decimalai skills add tooluniverseNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/tooluniverse/SKILL.md https://app.decimal.ai/s/tooluniverse/SKILL.md.agents/skills/tooluniverse/SKILL.mdThis gets SKILL.md only. The skill's 1 other file is not included.
Give its text to your model as instructions. No account or package needed.
This gets SKILL.md only. The skill's 1 other file is not included.
Raw files: /s/tooluniverse/SKILL.md · /s/tooluniverse.json
Fetch the file and give its text to your model as instructions. No account or package needed.
curl -fsSL https://app.decimal.ai/s/tooluniverse/SKILL.mdcurl -fsSL https://app.decimal.ai/s/tooluniverse.jsonThis gets SKILL.md only. The skill's 1 other file is not included.
You don't need a DecimalAI account.
Saved prompts and skills, pinned versions, and traces of this skill in your runs. DecimalAI does not run your agent.
Claude Code reads files from your project, so DecimalAI config does not apply there.
On Claude Agent SDK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On OpenAI Agents: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On OpenAI SDK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Anthropic: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Gemini API: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On LangChain: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On CrewAI: set DECIMAL_API_KEY and add decimalai.init(crewai=True) to record runs and skill use. The skill version stays in your repo.
On Google ADK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Pydantic AI: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Deep Agents: set DECIMAL_API_KEY and add decimalai.init(langchain=True) to record runs and skill use. The skill version stays in your repo.
On Microsoft Agent Framework: set DECIMAL_API_KEY and add decimalai.init(otel=True, agent_name="support") to record runs and skill use. The skill version stays in your repo.
On Strands: set DECIMAL_API_KEY and add decimalai.init(otel=True, agent_name="support") to record runs and skill use. The skill version stays in your repo.
Editors read files from your project, so DecimalAI config does not apply there.
Anywhere else: record a use with decimalai.log_skill_activation() inside a trace.
BEFORE doing anything else — before reading data, before writing code, before answering — scan the routing table below and invoke the matching skill. The specialized skill contains critical domain conventions that you will get wrong without loading.
How to route:
*mageck*.xlsx → CRISPR screen, *DM.csv/*AE.csv → clinical trial AE, *.vcf → variant, *.h5ad → single-cell, *_counts.csv+*meta*.csv → RNA-seq DE, *.faa+*.treefile → phylogenetics, *_executed.ipynb → authoritative analysis already ran)Skill(skill="<skill-name>") immediatelyIf no keyword matches but filenames indicate a domain → still route based on filename signals. Filenames are authoritative domain evidence even when the question prose is generic.
If no signal matches → use general strategies below.
DO NOT skip routing. Even if you think you know the answer, the skill has conventions (e.g., which denominator to use, which R function, which column to read) that differ from defaults.
Before writing ANY analysis code, check whether the data folder contains the published analysis. Two common forms:
Executed notebook (*_executed.ipynb, *.ipynb) — the analysis has already run with the exact package versions, filters, and thresholds behind the reference answers. Reimplementing with pydeseq2/scanpy/gseapy produces different numbers. Read the outputs directly:
tu run read_executed_notebook '{"data_folder":"/path/to/data","search":"<keyword>"}'
search can be comma-separated terms (e.g., "upregulated,log2FoldChange") or a regex. The tool returns the matching cells' source + printed outputs so you can cite the published value instead of recomputing.
Executable script (run_*.py, analysis.R, find_*.R, *.Rmd) — execute and report:
ls /path/to/data/folder
cd /path/to/data && python3 run_*.py # or Rscript analysis.R
Canonical vs scratch scripts: when a folder has many .R/.py files, prefer ones with canonical names (analysis.R, main.R, run.R, run_<question_topic>.R) over scratch-named ones (try_*.R, check_*.R, inspect_*.R, verify_*.R, *_v2.R, *2.R, *3.R). Scratch-named scripts are usually leftovers from prior agent attempts that may not have converged on the published answer — treat their outputs as advisory, not authoritative.
Only write your own analysis code when no authoritative pipeline exists in the data folder. When one does exist, your job is to execute/read it and report — not to reimplement.
RULE ZERO sub-rule — Cite-the-cell-output: If the notebook has a cell whose output IS the answer to the question (e.g., len(sigs) = 197, mean p-value: 0.0254, top hit: GENE_X), copy that output value directly. Do NOT recompute with your own filters. The notebook may apply slightly-different filters than the question text describes (e.g., the question lists padj<0.05, |LFC|>0.5, baseMean>10 but the notebook's filter line has & (baseMean>=10) commented out). The published answer is the notebook's output — even if the question's filter list slightly differs from what the notebook actually applied. The benchmark's GT comes from the notebook's actual computation, not from re-applying the question's literal filter list. Trust the notebook's published number when it directly answers the question.
Before writing your own analysis code, check these ready-made scripts in the plugin. They encode the correct conventions and save re-deriving them:
Prefer ToolUniverse tools (callable via tu run <name> or MCP execute_tool) for recurring analysis patterns. They encode the correct conventions:
| Task | ToolUniverse tool | One-liner |
|---|---|---|
| Read outputs of an authoritative executed notebook | read_executed_notebook | tu run read_executed_notebook '{"data_folder":"/path","search":"upregulated"}' |
| Clinical trial AE severity (chi-square, ordinal) | clinical_trial_ae_severity_test | tu run clinical_trial_ae_severity_test '{"dm_file":"DM.csv","ae_file":"AE.csv","test":"chi-square","group_col":"TRTGRP"}' |
| Per-gene ANOVA / fold change (gene × sample matrix) | expression_anova_per_gene | tu run expression_anova_per_gene '{"counts_file":"counts.csv","meta_file":"meta.csv","group_col":"cell_type","mode":"anova"}' |
| Coding-variant fraction in a VCF/Excel | coding_variant_fraction | tu run coding_variant_fraction '{"file":"variants.xlsx","vaf_threshold":0.3,"annotation":"synonymous_variant","header_rows":2}' |
| Batch PhyKIT on many trees | phykit_batch_analysis | tu run phykit_batch_analysis '{"operation":"batch","function":"treeness","directory":"./trees","extension":".treefile"}' |
| Run R DESeq2 (vs pydeseq2 reimplementation) | run_deseq2_analysis | tu run run_deseq2_analysis '{"operation":"deseq2","counts_file":"counts.csv","metadata_file":"meta.csv","design":"~ condition"}' |
Each tool handles encoding, column-name quirks, and aggregation-level edge cases that are easy to get wrong in ad-hoc code. Find more tools via tu find "<keyword>" or MCP find_tools.
These are short pointers. The full conventions, anti-pattern examples, and code snippets live in the matching sub-skill — load it via the routing table for the details.
max(AESEV) per subject, do NOT filter by AEPT — even when the question names a specific condition like "COVID-19 severity" or "infection severity", AESEV IS the universal outcome, not a subset filter. See tooluniverse-statistical-modeling.coding_variant_fraction tool. See tooluniverse-variant-analysis.tooluniverse-rnaseq-deseq2. When reading the analyst's filter line, only apply filters BEFORE the # comment — do NOT add filters from commented-out code (e.g., # & (baseMean>=10) is OFF, do not include).tooluniverse-statistical-modeling.ns() via Rscript — see tooluniverse-statistical-modeling.1-slope), not column 1 (slope) — see tooluniverse-phylogenetics.A ∩ B — see tooluniverse-rnaseq-deseq2.A/B = X AND B/A = 1/X in the final answer. English "ratio between A and B" is direction-ambiguous; reporting both ensures the correct value is in your response. Example output: "Ratio (W to 1) = 1.52, equivalently (1 to W) = 0.66".29, not 0.29). "proportion", "fraction", or "ratio" → report as decimal (e.g. 0.29). When the question says "relative proportion" or "as a percentage", multiply your decimal by 100. State both forms when there is any ambiguity (e.g. "0.29 (= 29%)").These reminders are for fast pattern recognition during routing. Detailed ❌ WRONG / ✅ RIGHT examples and sanity heuristics are in the sub-skill bodies — invoke the skill via the Routing Table to load them.
| Keywords | Action |
|---|---|
| "get", "retrieve", "chemical compound", "PubChem", "ChEMBL", "drug molecule", "SMILES", "InChI" | Skill(skill="tooluniverse-chemical-compound-retrieval") |
| "get", "retrieve", "expression data", "gene expression", "omics dataset", "ArrayExpress", "RNA-seq", "microarray" | Skill(skill="tooluniverse-expression-data-retrieval") |
| "get", "retrieve", "protein structure", "PDB", "AlphaFold", "crystal structure", "3D model" | Skill(skill="tooluniverse-protein-structure-retrieval") |
| "get", "retrieve", "sequence", "DNA sequence", "RNA sequence", "protein sequence", "FASTA" | Skill(skill="tooluniverse-sequence-retrieval") |
| "find data", "search datasets", "dataset", "where can I get data", "cohort study", "data repository", "public data", "download data for analysis", "what data exists for" | Skill(skill="tooluniverse-dataset-discovery") |
| "data wrangling", "download bulk data", "parse format", "API access pattern", "direct API", "raw data download", "beyond tools", "bulk download" | Skill(skill="tooluniverse-data-wrangling") |
| Keywords | Action |
|---|---|
| A single database-checkable fact, especially multiple-choice — "which of the following gene/drug/variant/pathway is…", anything phrased "according to " (DisGeNet, OMIM, MSigDB, miRDB, GTRD, MGI, Ensembl, ClinVar, ChEMBL, OpenTargets, UniProt). Look it up rather than answering from memory; niche annotations are what gets hallucinated | Skill(skill="tooluniverse-biomedical-fact-lookup") |
| "research", "profile", "disease", "syndrome", "disorder", "comprehensive report on [disease]" | Skill(skill="tooluniverse-disease-research") |
| "research", "profile", "drug", "medication", "therapeutic agent", "tell me about [drug]" | Skill(skill="tooluniverse-drug-research") |
| "literature review", "papers about", "publications on", "research articles", "recent studies" | Skill(skill="tooluniverse-literature-deep-research") |
| "research", "profile", "target", "protein target", "gene target", "target validation" | Skill(skill="tooluniverse-target-research") |
| "gene liability", "gene safety score", "knockout safety", "knockdown safety", "on-target toxicity", "safe to inhibit [gene]" | Skill(skill="tooluniverse-gene-liability") |
| "peptide target", "deorphanize", "deorphanization", "peptide off-target", "what does [peptide] bind", "target of a peptide", "orphan peptide", "peptide doesn't bind [target]", "binds in [species] but not", "find the receptor for [peptide]" | Skill(skill="tooluniverse-peptide-target-deorphanization") |
| Keywords | Action |
|---|---|
| "drug safety", "adverse events", "side effects", "pharmacovigilance", "pharmacogenomics", "FAERS", "black box warning" | Skill(skill="tooluniverse-pharmacovigilance") |
| "adverse event signal", "safety signal detection", "disproportionality", "PRR", "ROR" | Skill(skill="tooluniverse-adverse-event-detection") |
| "drug safety profile", "drug safety assessment", "comprehensive safety" | Skill(skill="tooluniverse-pharmacovigilance") |
| "chemical safety", "ADMET", "chemical toxicity", "environmental toxicity", "toxic effects" | Skill(skill="tooluniverse-chemical-safety") |
| "cancer treatment", "precision oncology", "tumor mutation", "targeted therapy", "EGFR", "KRAS", "BRAF" | Skill(skill="tooluniverse-precision-oncology") |
| "cancer driver", "driver gene", "driver mutation", "IntOGen", "cBioPortal" | Skill(skill="tooluniverse-cancer-genomics-tcga") |
| "somatic mutation interpretation", "cancer variant", "oncogenic variant", "tumor variant" | Skill(skill="tooluniverse-cancer-variant-interpretation") |
| "ACMG classification", "variant classification", "benign/pathogenic", "ACMG criteria", "PM2", "PS1", "PP3" | Skill(skill="tooluniverse-acmg-variant-classification") |
| "cancer classification", "OncoTree", "tumor subtype", "cancer type code", "histological classification" | Skill(skill="tooluniverse-cancer-classification") |
| "TCGA", "cancer genomics cohort", "GDC analysis", "TCGA mutations", "pan-cancer" | Skill(skill="tooluniverse-cancer-genomics-tcga") |
| "immunotherapy response", "checkpoint inhibitor response", "TMB", "MSI", "PD-L1", "ICI response" | Skill(skill="tooluniverse-immunotherapy-response-prediction") |
| "rare disease diagnosis", "differential diagnosis", "phenotype matching", "HPO", "patient with [symptoms]" | Skill(skill="tooluniverse-rare-disease-diagnosis") |
| "clinical risk score", "CHA2DS2-VASc", "HAS-BLED", "CURB-65", "qSOFA", "Child-Pugh", "MELD-Na", "Wells score", "ASCVD risk", "eGFR CKD-EPI", "bedside risk calculator" | Skill(skill="tooluniverse-clinical-risk-scoring") |
| "device adverse events", "device recall", "MAUDE", "food/supplement adverse event", "CAERS", "veterinary adverse event", "drug shortage" | Skill(skill="tooluniverse-product-safety-surveillance") |
| "variant interpretation", "VUS", "pathogenicity", "clinical significance", "is [variant] pathogenic" | Skill(skill="tooluniverse-variant-interpretation") |
| "clinical guidelines", "practice guidelines", "treatment guidelines", "dosing recommendations", "standard of care" | Skill(skill="tooluniverse-clinical-guidelines") |
| Drug choice for a described patient — "which of the following is most appropriate for", "which drug should this patient receive"; a vignette naming a modifier (hepatic/renal impairment, Child-Pugh, "on a strong CYP3A4 inhibitor", pregnancy, a contraindication) alongside candidate drugs. The deciding fact is in each candidate's FDA label, not recall | Skill(skill="tooluniverse-biomedical-fact-lookup") |
| "patient stratification", "precision medicine", "biomarker stratification", "treatment selection" | Skill(skill="tooluniverse-precision-medicine-stratification") |
| Keywords | Action |
|---|---|
| "find binders", "virtual screening", "hit identification", "compounds for [target]", "IC50", "bioactivity", "binding affinity", "potency", "selectivity", "SAR", "structure-activity", "lead optimization", "hit-to-lead" | Skill(skill="tooluniverse-binder-discovery") |
| "peptide target", "deorphanize", "deorphanization", "peptide off-target", "what does [peptide] bind", "target of a peptide", "orphan peptide", "peptide doesn't bind [target]", "binds in [species] but not", "find the receptor for [peptide]" | Skill(skill="tooluniverse-peptide-target-deorphanization") |
| "drug repurposing", "new indication", "existing drugs for [disease]", "repurpose [drug]" | Skill(skill="tooluniverse-drug-repurposing") |
| "drug target validation", "target druggability", "validate target", "target assessment" | Skill(skill="tooluniverse-drug-target-validation") |
| "network pharmacology", "polypharmacology", "compound-target network", "multi-target" | Skill(skill="tooluniverse-network-pharmacology") |
| Ongoing protein design validation — "protein design campaign", "validate binder candidates", "conflicting binder models", "conditional pH binder", "glycan clash validation", "protein competition submission" | Skill(skill="tooluniverse-protein-design-campaign") |
| "design protein", "protein binder", "de novo protein", "RFdiffusion", "ProteinMPNN" | Skill(skill="tooluniverse-protein-therapeutic-design") |
| "antibody engineering", "antibody design", "humanization", "affinity maturation" | Skill(skill="tooluniverse-antibody-engineering") |
| "ADMET prediction", "ADME", "absorption", "distribution", "metabolism", "excretion", "toxicity prediction" | Skill(skill="tooluniverse-admet-prediction") |
| "small molecule discovery", "chemical biology", "compound sourcing", "hit finding", "chemical probe" | Skill(skill="tooluniverse-small-molecule-discovery") |
| "chemical sourcing", "buy compound", "vendor search", "Enamine", "MolPort", "compound availability" | Skill(skill="tooluniverse-chemical-sourcing") |
| "GPCR", "G-protein coupled receptor", "GPCRdb", "receptor ligand", "biased agonist" | Skill(skill="tooluniverse-gpcr-structural-pharmacology") |
| "dereplicate", "natural product identification", "NPAtlas", "ChemOnt classification", "ClassyFire", "producing organism" | Skill(skill="tooluniverse-natural-product-dereplication") |
| Keywords | Action |
|---|---|
| "GWAS study", "genome-wide association", "GWAS catalog", "GWAS for [trait]" | Skill(skill="tooluniverse-gwas-study-explorer") |
| "GWAS trait to gene", "trait-associated genes", "causal genes", "genes for [trait]" | Skill(skill="tooluniverse-gwas-trait-to-gene") |
| "fine-mapping", "credible sets", "causal variants", "statistical refinement" | Skill(skill="tooluniverse-gwas-finemapping") |
| "SNP interpretation", "rsID", "rs[number]", "variant annotation" | Skill(skill="tooluniverse-gwas-snp-interpretation") |
| "polygenic risk", "PRS", "genetic risk", "risk score for [disease]" | Skill(skill="tooluniverse-polygenic-risk-score") |
| "structural variant", "SV", "CNV", "deletion", "duplication", "chromosomal rearrangement" | Skill(skill="tooluniverse-structural-variant-analysis") |
| "VCF", "variant calling", "mutation analysis", "variant annotation pipeline", "VAF", "variant allele frequency", "coding variant", "synonymous", "missense" | Skill(skill="tooluniverse-variant-analysis") |
| "variant functional annotation", "protein variant effect", "variant consequence", "missense effect" | Skill(skill="tooluniverse-variant-functional-annotation") |
| "regulatory variant", "non-coding variant", "eQTL variant", "regulatory region variant" | Skill(skill="tooluniverse-regulatory-variant-analysis") |
| "rare disease genomics", "Orphanet gene", "rare disease gene", "causative gene", "exome diagnosis" | Skill(skill="tooluniverse-rare-disease-genomics") |
| "1000 Genomes", "IGSR", "population frequency", "superpopulation", "AFR/EUR/EAS/SAS/AMR" | Skill(skill="tooluniverse-population-genetics-1000genomes") |
| "PheWAS", "phenome-wide association", "cross-ancestry replication", "cross-biobank", "FinnGen", "BioBank Japan", "pleiotropy of a variant" | Skill(skill="tooluniverse-phewas") |
| "Mendelian randomization", "MR causal inference", "instrumental variable", "does X cause Y", "genetic causal evidence" | Skill(skill="tooluniverse-mendelian-randomization") |
| "loss-of-function mechanism", "LoF mechanism", "why is this variant LoF", "structural stability vs functional disruption" | Skill(skill="tooluniverse-protein-lof-mechanism") |
| "SAE feature", "sparse autoencoder variant", "ESMC SAE", "mechanistic variant interpretation" | Skill(skill="tooluniverse-protein-sae-variant-interpretation") |
| "per-residue annotation", "binding interface residues", "ligand pocket residues", "buried vs surface residues", "PDB structural annotation" | Skill(skill="tooluniverse-protein-structural-annotation-pdb") |
| "why are these residues critical", "residue functional mechanism", "DMS hotspot interpretation", "catalytic vs structural residue" | Skill(skill="tooluniverse-residue-functional-mechanism-interpretation") |
| "validate variant predictor", "DMS validation", "deep mutational scanning benchmark", "predictor vs experimental effect" | Skill(skill="tooluniverse-variant-predictor-dms-validation") |
| Keywords | Action |
|---|---|
| "protein interactions", "PPI", "interactome", "binding partners", "protein complexes" | Skill(skill="tooluniverse-protein-interactions") |
| "systems biology", "pathway analysis", "network analysis", "gene set enrichment" | Skill(skill="tooluniverse-systems-biology") |
| "metabolomics", "metabolite identification", "metabolic pathway" | Skill(skill="tooluniverse-metabolomics") |
| "epigenomics", "gene regulation", "transcription factor", "TF binding", "enhancers", "chromatin", "ChIP-seq" | Skill(skill="tooluniverse-epigenomics") |
| "gene enrichment", "pathway enrichment", "GO enrichment", "GSEA", "overrepresentation", "gene list analysis" | Skill(skill="tooluniverse-gene-enrichment") |
| "multi-omics", "omics integration", "transcriptomics + proteomics", "integrated analysis" | Skill(skill="tooluniverse-multi-omics-integration") |
| "multi-omic disease", "disease characterization", "genomic + transcriptomic + proteomic" | Skill(skill="tooluniverse-multiomic-disease-characterization") |
| "gene regulatory network", "GRN", "TF network", "regulatory circuit", "gene regulation network" | Skill(skill="tooluniverse-gene-regulatory-networks") |
| "epigenomics chromatin", "histone modification", "chromatin accessibility", "ATAC-seq", "DNase-seq" | Skill(skill="tooluniverse-epigenomics-chromatin") |
| "pathway disease", "disease pathway", "pathway genetics", "pathway convergence" | Skill(skill="tooluniverse-pathway-disease-genetics") |
| "metabolomics pathway", "metabolic pathway mapping", "pathway-level metabolomics" | Skill(skill="tooluniverse-metabolomics-pathway") |
| "interpret results", "biological context", "beyond p-values", "what does this result mean", "integrate analysis with biology", "statistical results + biology", "causal reasoning", "evidence integration" | Skill(skill="tooluniverse-data-integration-analysis") |
| Keywords | Action |
|---|---|
| "CRISPR screen", "genetic screen", "screen hits", "essential genes", "MAGeCK", "sgRNA", "screen replicate", "screen QC", "dropout screen", "CRISPRa", "CRISPRi", "beta score" | Skill(skill="tooluniverse-crispr-screen-analysis") |
| "drug-drug interaction", "DDI", "drug combination", "polypharmacy" | Skill(skill="tooluniverse-drug-drug-interaction") |
| "differential expression", "DESeq2", "RNA-seq analysis", "DE genes", "fold change", "differentially expressed", "log2FC", "count matrix", "dispersion" | Skill(skill="tooluniverse-rnaseq-deseq2") |
| "proteomics", "mass spectrometry", "protein quantification", "TMT", "iTRAQ", "label-free" | Skill(skill="tooluniverse-proteomics-analysis") |
| "immune repertoire", "TCR", "BCR", "T-cell receptor", "B-cell receptor", "clonotype" | Skill(skill="tooluniverse-immune-repertoire-analysis") |
| "spatial transcriptomics", "Visium", "MERFISH", "seqFISH", "Slide-seq", "spatial gene expression" | Skill(skill="tooluniverse-spatial-transcriptomics") |
| "spatial omics", "spatial proteomics", "spatial multi-omics" | Skill(skill="tooluniverse-spatial-omics-analysis") |
| "microscopy", "image analysis", "cell counting", "colony morphometry", "fluorescence quantification" | Skill(skill="tooluniverse-image-analysis") |
| "electron microscopy", "cryo-EM", "TEM", "SEM", "EMPIAR", "EMDB" | Skill(skill="tooluniverse-electron-microscopy") |
| "cell line", "cell line profiling", "DepMap", "CCLE", "cell line sensitivity" | Skill(skill="tooluniverse-cell-line-profiling") |
| "clinical data integration", "clinical phenotype", "EHR analysis", "clinical cohort" | Skill(skill="tooluniverse-clinical-data-integration") |
| "phylogenetics", "phylogenetic tree", "sequence alignment", "evolutionary analysis", "treeness", "saturation", "parsimony", "PhyKIT", "DVMC", "long branch", "tree length", "MAFFT", "gap percentage" | Skill(skill="tooluniverse-phylogenetics") |
| "statistical modeling", "regression analysis", "logistic regression", "survival analysis", "Cox", "ANOVA", "F-statistic", "chi-square", "spline", "odds ratio", "Cohen's d", "p-value", "clinical trial data", "ordinal", "severity", "vaccination", "SDTM", "DM.csv", "AE.csv", "adverse event severity" | Skill(skill="tooluniverse-statistical-modeling") |
| "meta-analysis", "pool effect sizes", "pooled estimate", "evidence synthesis", "forest plot", "heterogeneity", "I-squared", "I²", "fixed-effects", "random-effects", "DerSimonian-Laird", "combine studies", "systematic review statistics", "multi-cohort pooling" | Skill(skill="tooluniverse-meta-analysis") |
| "dose-response", "concentration-response", "IC50", "EC50", "Hill slope", "potency", "4-parameter logistic", "4PL", "sigmoidal fit", "Emax", "relative potency", "fold-shift", "drug screening curve" | Skill(skill="tooluniverse-dose-response") |
| "pharmacokinetics", "PK analysis", "non-compartmental", "NCA", "Cmax", "Tmax", "AUC", "half-life", "clearance", "volume of distribution", "bioavailability", "concentration-time", "plasma concentration" | Skill(skill="tooluniverse-pharmacokinetics") |
| "enzyme kinetics", "Michaelis-Menten", "Km", "Vmax", "kcat", "turnover number", "catalytic efficiency", "specificity constant", "Lineweaver-Burk", "enzyme inhibition", "Ki", "competitive inhibitor" | Skill(skill="tooluniverse-enzyme-kinetics") |
| "primer design", "PCR primers", "qPCR primer", "melting temperature", "Tm calculation", "annealing temperature", "GC clamp", "primer-dimer", "oligo analysis", "amplicon", "forward and reverse primer" | Skill(skill="tooluniverse-primer-design") |
| "diagnostic test", "sensitivity specificity", "ROC curve", "AUC", "PPV", "NPV", "likelihood ratio", "Youden", "optimal cutoff", "post-test probability", "biomarker accuracy", "confusion matrix" | Skill(skill="tooluniverse-diagnostic-test-evaluation") |
| "drug synergy", "drug combination", "Bliss independence", "Loewe additivity", "HSA synergy", "ZIP score", "combination index", "Chou-Talalay", "synergistic antagonistic", "combination therapy analysis" | Skill(skill="tooluniverse-drug-synergy") |
| "molecular cloning", "Gibson Assembly", "Golden Gate", "Type IIS", "BsaI", "BbsI", "Esp3I", "BsmBI", "SapI", "assembly overlap", "fragment assembly", "construct design", "domestication", or the reverse direction — "I combined these plasmids…", "what does the resulting plasmid express", "what does the gRNA target", "virtual digest", "restriction digest of a plasmid" | Skill(skill="tooluniverse-molecular-cloning") |
| "metabolomics analysis", "LC-MS analysis", "metabolite quantification", "metabolic flux" | Skill(skill="tooluniverse-metabolomics-analysis") |
| "functional genomics screen", "CRISPR library", "shRNA screen", "barcode screen" | Skill(skill="tooluniverse-functional-genomics-screens") |
| "proteomics data", "PRIDE", "MassIVE", "ProteomeXchange", "proteomics dataset" | Skill(skill="tooluniverse-proteomics-data-retrieval") |
| "protein modification", "PTM analysis", "phosphorylation site", "ubiquitination", "glycosylation" | Skill(skill="tooluniverse-protein-modification-analysis") |
| "structural proteomics", "cross-linking mass spec", "XL-MS", "HDX-MS", "structural biology" | Skill(skill="tooluniverse-structural-proteomics") |
| "protein structure prediction", "AlphaFold prediction", "structure modeling", "homology modeling" | Skill(skill="tooluniverse-protein-structure-prediction") |
| "FASTQ QC", "FastQC", "MultiQC", "adapter trimming", "fastp", "Cutadapt", "read quality", "sequence duplication" | Skill(skill="tooluniverse-fastq-qc") |
| Keywords | Action |
|---|---|
| "clinical trial design", "trial protocol", "study design", "endpoint selection" | Skill(skill="tooluniverse-clinical-trial-design") |
| "clinical trial matching", "patient-to-trial", "trial eligibility", "find trials for patient" | Skill(skill="tooluniverse-clinical-trial-matching") |
| "GWAS drug discovery", "genetic target validation", "GWAS to drug" | Skill(skill="tooluniverse-gwas-drug-discovery") |
| "epidemiological analysis", "epidemiology", "risk factors", "exposure-outcome", "observational study", "confounder adjustment", "disease risk analysis", "analyze health data", "regression on clinical data", "survival analysis on cohort" | Skill(skill="tooluniverse-epidemiological-analysis") |
| Keywords | Action |
|---|---|
| "model organism", "mouse phenotype", "fly ortholog", "worm", "zebrafish", "yeast", "cross-species" | Skill(skill="tooluniverse-model-organism-genetics") |
| "comparative genomics", "ortholog", "paralog", "conservation", "evolutionary" | Skill(skill="tooluniverse-comparative-genomics") |
| "population genetics", "allele frequency", "HWE", "Fst", "genetic drift" | Skill(skill="tooluniverse-population-genetics") |
| "plant", "Arabidopsis", "crop", "plant pathway", "photosynthesis" | Skill(skill="tooluniverse-plant-genomics") |
| "microbiome", "metagenomics", "gut bacteria", "16S", "MGnify" | Skill(skill="tooluniverse-metagenomics-analysis") |
| "pathogen", "infectious disease", "outbreak", "emerging infection" | Skill(skill="tooluniverse-infectious-disease") |
| "ecology", "biodiversity", "invasive species", "pollinator", "food web", "conservation", "community ecology", "trophic" | Skill(skill="tooluniverse-ecology-biodiversity") |
| "microbiome", "gut microbiota", "dysbiosis", "microbiome composition", "16S rRNA" | Skill(skill="tooluniverse-microbiome-research") |
| "adverse outcome pathway", "AOP", "key event", "molecular initiating event", "KER" | Skill(skill="tooluniverse-adverse-outcome-pathway") |
| "genome assembly", "assembly N50", "RefSeq assembly QC", "plasmid count", "NCBI Datasets genome" | Skill(skill="tooluniverse-microbial-genome-characterization") |
| Keywords | Action |
|---|---|
| "lipidomics", "lipid", "sphingolipid", "ceramide", "fatty acid", "LIPID MAPS" | Skill(skill="tooluniverse-lipidomics") |
| "miRNA", "lncRNA", "non-coding RNA", "microRNA", "ncRNA" | Skill(skill="tooluniverse-noncoding-rna") |
| "aging", "senescence", "longevity", "senolytic", "geroprotector" | Skill(skill="tooluniverse-aging-senescence") |
| "vaccine", "epitope prediction", "MHC binding", "immunogenicity", "T-cell epitope" | Skill(skill="tooluniverse-vaccine-design") |
| "stem cell", "iPSC", "organoid", "pluripotency", "differentiation" | Skill(skill="tooluniverse-stem-cell-organoid") |
| "single cell", "scRNA-seq", "cell clustering", "UMAP", "cell type" | Skill(skill="tooluniverse-single-cell") |
| "pharmacogenomics", "PGx", "CPIC", "CYP2D6", "drug-gene", "genotype-guided dosing" | Skill(skill="tooluniverse-pharmacogenomics") |
| "drug mechanism", "mechanism of action", "how does [drug] work", "MOA" | Skill(skill="tooluniverse-drug-mechanism-research") |
| "drug regulatory", "FDA approval", "generic availability", "Orange Book", "patent" | Skill(skill="tooluniverse-drug-regulatory") |
| "gene-disease", "disease genes", "gene association", "genetic basis" | Skill(skill="tooluniverse-gene-disease-association") |
| "toxicology", "AOP", "adverse outcome pathway", "toxin", "BPA" | Skill(skill="tooluniverse-toxicology") |
| "variant to mechanism", "how does variant cause disease", "trace variant" | Skill(skill="tooluniverse-variant-to-mechanism") |
| "regulatory genomics", "enhancer", "promoter", "ENCODE", "cis-regulatory" | Skill(skill="tooluniverse-regulatory-genomics") |
| "KEGG disease", "KEGG drug", "KEGG pathway disease" | Skill(skill="tooluniverse-kegg-disease-drug") |
| "HLA", "MHC", "antigen presentation", "transplant compatibility" | Skill(skill="tooluniverse-hla-immunogenomics") |
| "immunology", "immune response", "cytokine", "antibody-antigen", "autoimmune", "immune signaling" | Skill(skill="tooluniverse-immunology") |
| "neuroscience", "neuron", "brain", "synapse", "neural network", "firing rate", "computational neuroscience", "neuroanatomy", "neurodegeneration", "cranial nerve", "action potential", "connectome" | Skill(skill="tooluniverse-neuroscience") |
| Keywords | Action |
|---|---|
| "organic chemistry", "reaction mechanism", "predict product", "NMR interpretation", "IUPAC name", "Diels-Alder", "Grignard", "stereochemistry", "retrosynthesis" | Skill(skill="tooluniverse-organic-chemistry") |
| "inorganic chemistry", "crystal structure", "unit cell", "coordination", "point group", "symmetry", "noble gas compound", "lanthanide", "covalency", "bonding theory", "thermodynamics", "Nernst" | Skill(skill="tooluniverse-inorganic-physical-chemistry") |
| "calculate", "compute", "dosing calculation", "drip rate", "half-life decay", "dilution", "R₀", "herd immunity", "partition function", "pharmacokinetics", "stoichiometry" | Skill(skill="tooluniverse-computational-biophysics") |
| "neural model", "firing rate", "integrate-and-fire", "synaptic dynamics", "network model", "balanced network" | Skill(skill="tooluniverse-neuroscience") |
| "environmental calculation", "contaminant dilution", "bioconcentration", "mass balance", "environmental fate" | Skill(skill="tooluniverse-computational-biophysics") |
| Keywords | Action |
|---|---|
| "setup", "install", "configure", "API keys", "upgrade", "how to use", "get started", "CLI", "tu command", "MCP vs CLI vs SDK", "what is ToolUniverse", "what can this do", "what databases", "demo", "tutorial", "quickstart", "I'm new" | Skill(skill="tooluniverse-claude-code-plugin") |
| "custom tool", "add my own tool", "local tool", "create tool", "extend ToolUniverse" | Skill(skill="tooluniverse-custom-tool") |
| "SDK", "Python SDK", "build AI scientist", "programmatic access", "import tooluniverse", "coding API", "tu build", "typed wrappers" | Skill(skill="tooluniverse-sdk") |
| "install skills", "missing skills", "skill not found", "add skills" | Skill(skill="tooluniverse-install-skills") |
| "self-review", "eval current work", "evaluate this work", "check my work", "is this complete", "definition of done", "evaluation rubric", "success criteria", "grading criteria", "LLM-as-judge" | Skill(skill="tooluniverse-self-review") |
| Keywords | Action |
|---|---|
| "share my model/script/function", "let my lab/colleague use this", "make this a tool", "share my GPU", "keep my tool running" | Skill(skill="tooluniverse-share-computer") |
| "publish my tool", "put it in Discover", "let anyone use my tool", "unpublish" | Skill(skill="tooluniverse-publish-tool") |
| "API key missing", "login/token rejected", "add my OMIM/NCBI/DisGeNET key", "which logins do I need" | Skill(skill="tooluniverse-database-logins") |
| "TU-SHARE-" code, "use my colleague's model/computer", "run it on the lab GPU", "shared or community tools" | Skill(skill="tooluniverse-use-shared-computer") |
Computation Over Lookup: When a question requires calculation, reasoning, or mechanism prediction, route to the problem-solving skill even if a data-retrieval skill also matches.
Domain Over Setup: When "how do I", "help me", "explain", or "what is" co-occurs with a domain entity (drug, gene, protein, disease, variant, pathway name), route to the domain skill, NOT setup.
Specificity Rule: More specific beats general.
Evaluation Intent Rule: Route requests to review existing/current work to
tooluniverse-self-review, but do not route requests to create or run an eval suite,
grader, test, or benchmark there. Those are implementation tasks. Within self-review,
plain "eval" is qualitative; scoring requires an explicit score/grade/points request.
Data Type Rule: "get/retrieve/fetch" → retrieval skills.
Still ambiguous: Ask user with AskUserQuestion.
Only when no specialized skill matches:
WARNING: "how do I find interactions for TP53?" is NOT a meta-question — route to protein-interactions.
When using general strategies, load references/general-strategies.md and execute them (run actual queries, don't just describe).
Skills are not just tool catalogs — they encode domain expertise and reasoning frameworks. When a question requires reasoning, computation, or clinical judgment (not just data lookup), route to the appropriate problem-solving skill.
tooluniverse-computational-biophysicstooluniverse-organic-chemistryThink first, then look up. Many scientific problems require reasoning frameworks + computation, not just database queries. Skills should help you SOLVE problems, not just find data.
These scripts are available across skills for quick local computation — invoke them directly when routing to the corresponding skill:
| Script | Skill | Use When | ToolUniverse Tool Alternative (preferred) |
|---|---|---|---|
skills/tooluniverse-computational-biophysics/scripts/iv_drip_rate.py | computational-biophysics | IV drip rate / dosing calculations | -- |
skills/tooluniverse-computational-biophysics/scripts/herd_immunity.py | computational-biophysics | R₀, herd immunity threshold | Epidemiology_r0_herd |
skills/tooluniverse-computational-biophysics/scripts/epidemiology.py | computational-biophysics | Epidemiology calculations | Epidemiology_r0_herd, Epidemiology_vaccine_coverage, Epidemiology_nnt, Epidemiology_diagnostic, Epidemiology_bayesian |
skills/tooluniverse-computational-biophysics/scripts/radioactive_decay.py | computational-biophysics | Radioactive decay / half-life | -- |
skills/tooluniverse-computational-biophysics/scripts/fluid_calculations.py | computational-biophysics | Fluid dynamics / flow calculations | -- |
skills/tooluniverse-computational-biophysics/scripts/burn_fluids.py | computational-biophysics | Burn injury fluid resuscitation | -- |
skills/tooluniverse-computational-biophysics/scripts/enzyme_kinetics.py | computational-biophysics | Km/Vmax, Hill coefficient, Ki from data | EnzymeKinetics_calculate |
skills/tooluniverse-computational-biophysics/scripts/env_risk_assessment.py | computational-biophysics | Soil contamination hazard quotient | -- |
skills/tooluniverse-drug-drug-interaction/scripts/pharmacology_ref.py | drug-drug-interaction | CYP substrates, drug interactions, pharmacology constants | -- |
skills/tooluniverse-rare-disease-diagnosis/scripts/clinical_patterns.py | rare-disease-diagnosis | HPO pattern matching, differential diagnosis | -- |
skills/tooluniverse-sequence-analysis/scripts/translate_dna.py | sequence-analysis | DNA → protein translation | DNA_translate_reading_frames |
skills/tooluniverse-sequence-analysis/scripts/amino_acids.py | sequence-analysis | Amino acid properties lookup | -- |
skills/tooluniverse-sequence-analysis/scripts/sequence_tools.py | sequence-analysis | GC content, reverse complement, motif scan | Sequence_count_residues, Sequence_gc_content, Sequence_reverse_complement, Sequence_stats |
skills/tooluniverse-sequence-analysis/scripts/biology_facts.py | sequence-analysis | Genetic code, codon tables, biology constants | -- |
skills/tooluniverse-organic-chemistry/scripts/degrees_of_unsaturation.py | organic-chemistry | Degrees of unsaturation from formula | DegreesOfUnsaturation_calculate |
skills/tooluniverse-organic-chemistry/scripts/molecular_formula.py | organic-chemistry | Molecular weight, formula parsing | MolecularFormula_analyze |
skills/tooluniverse-organic-chemistry/scripts/chemistry_facts.py | organic-chemistry | Functional groups, reaction types reference | -- |
skills/tooluniverse-organic-chemistry/scripts/molecular_complexity.py | organic-chemistry | Böttcher/Bertz molecular complexity | -- |
skills/tooluniverse-organic-chemistry/scripts/crystal_validator.py | organic-chemistry | Crystal structure density validation | CrystalStructure_validate |
skills/tooluniverse-organic-chemistry/scripts/stereochem_tracker.py | organic-chemistry | Track R/S through reaction sequences | -- |
skills/tooluniverse-organic-chemistry/scripts/smiles_verifier.py | organic-chemistry | Verify SMILES: MW, heavy atoms, valence electrons | SMILES_verify |
skills/tooluniverse-population-genetics/scripts/popgen_calculator.py | population-genetics | HWE, Fst, allele frequency calculations | PopGen_hwe_test, PopGen_fst, PopGen_inbreeding, PopGen_haplotype_count |
skills/tooluniverse-metabolomics/scripts/metabolism_ref.py | metabolomics | Pathway lookup, 13C tracer, ATP yield | -- |
skills/tooluniverse-variant-analysis/scripts/parse_vcf.py | variant-analysis | Parse VCF files locally | -- |
For factoid questions (short answer expected), don't generate a full research report. Instead:
Examples:
Key principle: If you're uncertain about a scientific fact, look it up in a database rather than answering from memory.
Clear match: "comprehensive research report on breast cancer" → Skill(skill="tooluniverse-disease-research", args="breast cancer")
Factoid lookup: "How many cysteine residues in GABAAρ1 TM3-TM4 linker?" → Skill(skill="tooluniverse-sequence-analysis") → UniProt lookup → count
Ambiguous: "Tell me about aspirin" → AskUserQuestion: drug profile, safety, chemical data, or repurposing?
No match: "How can I find all tools related to proteomics?" → General strategies: run find_tools queries
Domain + setup keyword: "help me understand BRCA1 variants" → Skill(skill="tooluniverse-variant-interpretation", args="BRCA1")
Published skills whose descriptions closely match this one, with their headline benchmark lift.
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.