Install any skill in seconds. Free to start, no credit card required.
Get Started Free →NACUBO endowment data (~650 institutions, 2012-2022). Portal: 7 columns only (total endowment, per-FTE, YoY change).
SkillScore96/100
Test results 96
3/3 safety checks passed
36%96%of test cases passed +60 pts
Passed 24 of 25 test cases with the skill, and 9 of 25 without it.
15 fixed9 passed either way1 still failing0 broke
One test taskWhen querying the NACUBO portal mirror table `nacubo/colleges_nacubo_endow`, is the `endow_total` column reported in thousands of dollars or raw USD?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add brycewang-stanford-education-data-source-nacubo
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("brycewang-stanford-education-data-source-nacubo")
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 brycewang-stanford-education-data-source-nacuboThe 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/brycewang-stanford-education-data-source-nacubo/SKILL.md https://app.decimal.ai/s/brycewang-stanford-education-data-source-nacubo/SKILL.md.claude/skills/brycewang-stanford-education-data-source-nacubo/SKILL.mdThis gets SKILL.md only. The skill's 5 other files are 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 brycewang-stanford-education-data-source-nacuboimport 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacubofrom 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacuboimport 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacuboimport 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacubofrom 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacubofrom 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacuboimport 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacubofrom 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacubofrom 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are not included.
Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagents
decimalai skills add brycewang-stanford-education-data-source-nacuboimport 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are not included.
Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-framework
decimalai skills add brycewang-stanford-education-data-source-nacuboimport 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are not included.
Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agents
decimalai skills add brycewang-stanford-education-data-source-nacubofrom 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("brycewang-stanford-education-data-source-nacubo")
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/brycewang-stanford-education-data-source-nacubo/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/brycewang-stanford-education-data-source-nacubo/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 5 other files are 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 brycewang-stanford-education-data-source-nacuboNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/brycewang-stanford-education-data-source-nacubo/SKILL.md https://app.decimal.ai/s/brycewang-stanford-education-data-source-nacubo/SKILL.md.agents/skills/brycewang-stanford-education-data-source-nacubo/SKILL.mdThis gets SKILL.md only. The skill's 5 other files are not included.
Give its text to your model as instructions. No account or package needed.
This gets SKILL.md only. The skill's 5 other files are not included.
Raw files: /s/brycewang-stanford-education-data-source-nacubo/SKILL.md · /s/brycewang-stanford-education-data-source-nacubo.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/brycewang-stanford-education-data-source-nacubo/SKILL.mdcurl -fsSL https://app.decimal.ai/s/brycewang-stanford-education-data-source-nacubo.jsonThis gets SKILL.md only. The skill's 5 other files are 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.
NACUBO endowment data for U.S. college and university endowments (~650 institutions). Portal mirror provides only 7 market-value columns (total endowment, per-FTE endowment, year-over-year change; 2012-2022). Use when analyzing institution-level endowment size or trends. Full investment returns, asset allocations, spending rates, and governance data require separate NACUBO study access. For comprehensive endowment coverage across all institutions, use IPEDS finance data.
The NACUBO-Commonfund Study of Endowments (NCSE) is the most comprehensive annual survey of U.S. college and university endowments, covering ~650 institutions representing over $870 billion in assets. The Education Data Portal mirrors a limited subset (7 market-value columns); full investment, allocation, spending, and governance data requires direct NACUBO access.
CRITICAL: Portal Mirror Scope
The Education Data Portal mirrors contain only 7 columns of endowment data, focused on market values. Full investment data (returns, asset allocations, spending rates, governance) requires access to the complete NACUBO study.
Portal columns:
year,unitid,inst_name_nacubo,fips,endow_total,endow_per_fte,endow_chg_mktvalValue Encoding:
Variable Portal Format Notes fipsInteger ( 6= California)Not string abbreviations ("CA") yearInteger ( 2022)Fiscal year ending year endow_totalFloat64 (USD) Full dollar amount, NOT thousands endow_chg_mktvalFloat64 (decimal fraction) 0.059= 5.9% change, NOT5.9Missing data nullNOT -1, -2, -3 See
./references/variable-definitions.mdfor complete encoding tables.
The National Association of College and University Business Officers (NACUBO) is a nonprofit professional organization representing chief administrative and financial officers at higher education institutions.
unitid (IPEDS 6-digit institution ID)| File | Purpose | When to Read |
|---|---|---|
endowment-study.md | NCSE methodology, participation, history | Understanding data source context |
endowment-metrics.md | Market values, returns, spending rates | Interpreting performance data |
variable-definitions.md | Key variables, size categories, institution types | Building queries, filtering data |
data-quality.md | Coverage limitations, data caveats | Assessing data reliability |
asset-allocation.md | Investment categories, alternative strategies | Analyzing portfolio composition |
Endowment research topic?
├─ Market values / fund size
│ ├─ Individual institution values → NCSE public tables
│ ├─ Size distribution → ./references/variable-definitions.md
│ └─ Historical trends → ./references/endowment-metrics.md
├─ Investment returns
│ ├─ One-year returns → ./references/endowment-metrics.md
│ ├─ Multi-year returns (3/5/10/25-year) → ./references/endowment-metrics.md
│ └─ Returns by size/type → ./references/variable-definitions.md
├─ Asset allocation
│ ├─ Traditional vs alternative → ./references/asset-allocation.md
│ ├─ Private equity/VC allocation → ./references/asset-allocation.md
│ └─ ESG/responsible investing → ./references/asset-allocation.md
├─ Spending and distributions
│ ├─ Spending rates → ./references/endowment-metrics.md
│ ├─ Spending purposes (aid, faculty, etc.) → ./references/endowment-metrics.md
│ └─ Budget contribution → ./references/endowment-metrics.md
└─ Data quality concerns
├─ Coverage/participation → ./references/data-quality.md
├─ Self-reported data issues → ./references/data-quality.md
└─ Comparability across years → ./references/data-quality.md
Comparing NACUBO vs IPEDS for endowment data?
├─ Need ALL institutions → Use IPEDS (mandatory reporting)
├─ Need investment returns → Use NACUBO (IPEDS doesn't have)
├─ Need asset allocations → Use NACUBO (IPEDS doesn't have)
├─ Need spending rates → Use NACUBO (IPEDS doesn't have)
├─ Need just market values → Either works
│ ├─ More institutions → IPEDS
│ └─ More detail → NACUBO
└─ Need governance/policies → Use NACUBO (IPEDS doesn't have)
Which study by year?
├─ FY2023-present → NACUBO-Commonfund Study of Endowments (NCSE)
├─ FY2018-FY2022 → NACUBO-TIAA Study of Endowments (NTSE)
├─ FY2009-FY2017 → NACUBO-Commonfund Study of Endowments (NCSE)
└─ Before FY2009 → NACUBO Endowment Study (NES)
Portal Coverage Note: The Education Data Portal mirrors contain only 7 columns focused on endowment market values. Full investment data (returns, asset allocations, spending rates, governance) requires access to the complete NACUBO study. See "Full Report Access" section below.
These are the only columns available in the Portal mirror (nacubo/colleges_nacubo_endow):
| Column | Type | Description | Nulls |
|---|---|---|---|
year | Int64 | Fiscal year ending year (2012-2022) | 0 |
unitid | Int64 | IPEDS 6-digit institution ID | 0 |
inst_name_nacubo | String | NACUBO institution name | 0 |
fips | Int64 | State FIPS code (1-56, territories: 72, 78) | 1 |
endow_total | Float64 | Total endowment market value in USD (full dollars, NOT thousands) | 0 |
endow_per_fte | Float64 | Endowment per FTE student in USD | 1,260 (~15%) |
endow_chg_mktval | Float64 | Year-over-year market value change as decimal fraction (0.059 = 5.9%) | 3,972 (~48%) |
Important format notes:
endow_total is in full USD (e.g., 1.05e9 = $1.05 billion), not in thousandsendow_chg_mktval is a decimal fraction, not a percentage (multiply by 100 for display)# Correct: convert decimal fraction to percentage for display
df = df.with_columns(
(pl.col("endow_chg_mktval") * 100).alias("pct_change")
)
# Correct: endow_total is already in full USD
df.filter(pl.col("endow_total") > 1_000_000_000) # Endowments over $1B
| Metric | Description | In Portal Mirror? | Granularity |
|---|---|---|---|
| Market Value | Total endowment assets (FMV) | Yes (endow_total) | Institution-level |
| Market Value Per FTE | Endowment per FTE student | Yes (endow_per_fte) | Institution-level |
| Market Value Change | Year-over-year change | Yes (endow_chg_mktval) | Institution-level |
| Investment Return | Time-weighted return, net of fees | No (full study only) | 1, 3, 5, 10, 25-year periods |
| Effective Spending Rate | Annual withdrawal as % of market value | No (full study only) | Institution type, size |
| Asset Allocation | Portfolio composition by asset class | No (full study only) | Size category, type |
| New Gifts | Donations added to endowment | No (full study only) | Aggregate by size/type |
| Budget Support | Endowment % of operating budget | No (full study only) | Size category, type |
| ID | Format | Level | Example | Notes |
|---|---|---|---|---|
unitid | Integer (6-digit) | Institution | 166027 | IPEDS institution ID; primary join key |
inst_name_nacubo | String | Institution | Harvard University | NACUBO version of name |
fips | Integer (1-56) | State | 25 (Massachusetts) | State FIPS code |
| Category Code | Range | FY24 Count | % of Participants |
|---|---|---|---|
| 1 | Over $5 Billion | ~25 | ~4% |
| 2 | $1 Billion to $5 Billion | ~107 | ~16% |
| 3 | $501 Million to $1 Billion | ~77 | ~12% |
| 4 | $251 Million to $500 Million | ~97 | ~15% |
| 5 | $101 Million to $250 Million | ~161 | ~24% |
| 6 | $51 Million to $100 Million | ~111 | ~17% |
| 7 | Under $50 Million | ~80 | ~12% |
| Type Code | Type Name | Description |
|---|---|---|
| 1 | Private | Private colleges and universities |
| 2 | Public | Public colleges and universities |
| 3 | IRF | Institutionally Related Foundations |
| 4 | Combined | Combined endowment/foundation |
| Period | Average Range | Notes |
|---|---|---|
| 1-year | -8% to +31% | High volatility |
| 3-year | 3% to 15% | Less volatile |
| 5-year | 5% to 12% | More stable |
| 10-year | 6% to 9% | Most commonly cited |
| 25-year | 6% to 9% | Long-term benchmark |
| Code | Meaning | When Used |
|---|---|---|
null | Not reported / missing | Standard for all NACUBO variables |
Note: Unlike other Education Data Portal sources (CCD, CRDC, etc.), NACUBO data uses null values for missing data rather than coded values like -1, -2, -3. NACUBO is a voluntary survey with simpler missing data patterns; the Portal preserves null rather than applying coded values.
# Correct: Check for null
df.filter(pl.col("endow_per_fte").is_null())
# Incorrect: Checking for -1/-2/-3 (these don't exist in NACUBO)
# df.filter(pl.col("endow_per_fte") == -1) # Won't find anything
Datasets for NACUBO are available via the mirror system. See datasets-reference.md for canonical paths, mirrors.yaml for mirror configuration, and fetch-patterns.md for fetch code patterns.
| Dataset | Type | Years | Path | Codebook |
|---|---|---|---|---|
| Endowments | Single | 2012-2022 | nacubo/colleges_nacubo_endow | nacubo/codebook_colleges_nacubo_endowments |
Codebooks are .xls files co-located with data in all mirrors. Use get_codebook_url() from fetch-patterns.md to construct download URLs:
url = get_codebook_url("nacubo/codebook_colleges_nacubo_endowments")
Truth Hierarchy: When interpreting variable values, apply this priority:
- Actual data file (what you observe in the parquet/CSV) -- this IS the truth
- Live codebook (.xls in mirror) -- authoritative documentation, may lag
- This skill documentation -- convenient summary, may drift from codebook
If this documentation contradicts the codebook, trust the codebook. If the codebook contradicts observed data, trust the data and investigate.
Free tables available at: https://www.nacubo.org/Research/2024/Public-NCSE-Tables
Includes:
| Pitfall | Issue | Solution |
|---|---|---|
| Using NCES-style codes | Portal uses integer FIPS, not string state abbreviations | Use integer fips codes (1-56) |
| Expecting coded missing values | NACUBO in Portal uses nulls, not -1/-2/-3 | Check for null, not negative codes |
Treating endow_chg_mktval as percentage | Column is a decimal fraction (0.059), not a percentage (5.9) | Multiply by 100 for display: pl.col("endow_chg_mktval") * 100 |
Treating endow_total as thousands | Column is in full USD (1.05e9 = $1.05B) | No division needed; value is already in dollars |
| Comparing to IPEDS values | NACUBO is voluntary (~650-813), IPEDS is mandatory (~6,000+) | Note sample differences in analysis |
| Year interpretation | FY2024 = July 2023 - June 2024 | Align fiscal year definitions carefully |
| Assuming comprehensive coverage | Only ~650-813 of ~4,000+ institutions participate | Use IPEDS for population-level analysis |
| Ignoring partner changes | TIAA (2018-22) vs Commonfund (other years) may change methodology | Check methodology for specific years |
| Expecting investment returns in Portal | Portal only has market values, not returns/allocations/spending | Use full NCSE study for investment analysis |
| Issue | Impact | Mitigation |
|---|---|---|
| Portal subset | Only 7 columns mirrored (market values only) | Full study required for returns, allocations, spending, governance |
| Voluntary participation | ~650-813 of ~4,000+ institutions per year | Use IPEDS for comprehensive coverage |
| Self-reported data | Unverified accuracy | Cross-reference with IPEDS where possible |
| Selection bias | Larger, well-resourced institutions overrepresented | Analyze by size category |
| Partner changes | TIAA (2018-22), Commonfund (other years) | Check methodology changes |
| Fiscal year timing | July 1 - June 30 | Match to other data sources carefully |
| Declining participation | 813 in 2012 to 652 in 2021 in Portal data | Account for sample size changes in trend analysis |
| Research Question | Primary Variables | Reference File |
|---|---|---|
| How do endowment returns vary by size? | Return rates, size category | endowment-metrics.md |
| What drives endowment spending decisions? | Spending rate, spending policy | endowment-metrics.md |
| How are endowments invested? | Asset allocation percentages | asset-allocation.md |
| Which schools have the largest endowments? | Market value, institution name | Public tables |
| How has endowment performance changed? | Historical return series | endowment-metrics.md |
| What portion of budgets come from endowments? | Budget support percentage | endowment-metrics.md |
| Source | Relationship | When to Use |
|---|---|---|
education-data-source-ipeds | Complementary; mandatory reporting covers all institutions | Need all institutions or just market values |
education-data-source-scorecard | Complementary; student outcomes | Linking endowment size to student outcomes |
education-data-explorer | Parent discovery skill | Finding available endpoints |
education-data-query | Data fetching | Downloading parquet/CSV files |
| Topic | Reference File |
|---|---|
| Study methodology | ./references/endowment-study.md |
| Partnership history | ./references/endowment-study.md |
| Participation criteria | ./references/endowment-study.md |
| Investment returns | ./references/endowment-metrics.md |
| Spending rates | ./references/endowment-metrics.md |
| Market values | ./references/endowment-metrics.md |
| Size categories | ./references/variable-definitions.md |
| Institution types | ./references/variable-definitions.md |
| Variable list | ./references/variable-definitions.md |
| Asset classes | ./references/asset-allocation.md |
| Alternative investments | ./references/asset-allocation.md |
| ESG investing | ./references/asset-allocation.md |
| Selection bias | ./references/data-quality.md |
| Coverage gaps | ./references/data-quality.md |
| Comparability issues | ./references/data-quality.md |
Automatically, when a task matches. Use for endowment size/trends. Full investment/spending needs direct NACUBO access. For all-institution coverage use IPEDS finance.
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.