Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Drive the canonical spec-kitty next --mission <handle> control loop for mission advancement. Load agent profiles at init, apply action-scoped doctrine context at each step boundary, and pull specific tactics/directives on demand. Triggers: "run the next step", "what should runtime do next", "advance the mission", "what is the next task", "continue the workflow", "what step comes next". Does NOT handle: setup or repair requests, purely editorial glossary or doctrine maintenance, or direct code re
SkillScore91/100
Test results 91
3/3 safety checks passed
23%91%of test cases passed +68 pts
Passed 20 of 22 test cases with the skill, and 5 of 22 without it.
15 fixed5 passed either way2 still failing0 broke
One test taskI want to check what action the runtime recommends for mission 'data-pipeline' without advancing its state or claiming that the previous action succeeded. Which exact command should I run?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add priivacy-ai-spec-kitty-runtime-next
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("priivacy-ai-spec-kitty-runtime-next")
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 priivacy-ai-spec-kitty-runtime-nextThe 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/priivacy-ai-spec-kitty-runtime-next/SKILL.md https://app.decimal.ai/s/priivacy-ai-spec-kitty-runtime-next/SKILL.md.claude/skills/priivacy-ai-spec-kitty-runtime-next/SKILL.mdThis gets SKILL.md only. The skill's 2 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 priivacy-ai-spec-kitty-runtime-nextimport 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextfrom 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextimport 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextimport 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextfrom 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextfrom 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextimport 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextfrom 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextfrom 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextimport 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextimport 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextfrom 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("priivacy-ai-spec-kitty-runtime-next")
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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/priivacy-ai-spec-kitty-runtime-next/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 2 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 priivacy-ai-spec-kitty-runtime-nextNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/priivacy-ai-spec-kitty-runtime-next/SKILL.md https://app.decimal.ai/s/priivacy-ai-spec-kitty-runtime-next/SKILL.md.agents/skills/priivacy-ai-spec-kitty-runtime-next/SKILL.mdThis gets SKILL.md only. The skill's 2 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 2 other files are not included.
Raw files: /s/priivacy-ai-spec-kitty-runtime-next/SKILL.md · /s/priivacy-ai-spec-kitty-runtime-next.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/priivacy-ai-spec-kitty-runtime-next/SKILL.mdcurl -fsSL https://app.decimal.ai/s/priivacy-ai-spec-kitty-runtime-next.jsonThis gets SKILL.md only. The skill's 2 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.
This skill teaches agents how to advance a Spec Kitty mission through the canonical runtime control loop, including doctrine-aware context loading at each step boundary.
Use this skill when the user wants to:
The spec-kitty next command is the single entry point for agent-driven mission
execution. Each call returns a deterministic decision about what action the
agent should take next.
The runtime evaluates state in this order:
mission-runtime.yaml DAG)implement and review steps, the CLI bridge
manages WP-level iteration WITHOUT advancing the runtime. The runtime only
advances when ALL WPs reach terminal/handoff lanes.The CLI bridge (not the runtime) manages WP-level iteration:
implement or reviewplanned or in_progress lanesdone, approved, or for_review)This means multiple calls to spec-kitty next during implementation will
return different WP IDs but the same step_id (e.g., "implement") until all
WPs are done.
Missions define steps as a DAG (directed acyclic graph) with dependencies:
mission:
key: software-dev
name: Software Dev Kitty
version: "2.1.0"
steps:
- id: discovery
title: Discovery & Research
depends_on: []
prompt_template: research.md
- id: specify
depends_on: [discovery]
prompt_template: specify.md
- id: plan
depends_on: [specify]
prompt_template: plan.md
- id: tasks
depends_on: [plan]
- id: implement
depends_on: [tasks]
prompt_template: implement.md
- id: review
depends_on: [implement]
prompt_template: review.md
- id: accept
depends_on: [review]
prompt_template: accept.md
Every call to spec-kitty next returns exactly one decision kind:
| Kind | Meaning | Agent Action |
|---|---|---|
step | Normal action available | Read prompt_file and execute |
query | Read-only current-state preview | Inspect state; do not execute a prompt or mark a result |
decision_required | Runtime needs input | Answer with --answer and --decision-id |
blocked | Guards failing, cannot proceed | Read reason + guard_failures, resolve blockers |
terminal | Mission complete | Run /spec-kitty.accept; if it passes, merge, then: mission review → author or verify retrospective (retrospect create) → surface findings (summary aggregates; synthesize reviews proposals) |
{
"kind": "step",
"agent": "claude",
"mission_slug": "042-test-mission",
"mission": "software-dev",
"mission_state": "implementing",
"action": "implement",
"wp_id": "WP02",
"workspace_path": ".worktrees/042-test-mission-lane-b",
"prompt_file": "/tmp/spec-kitty-next-claude-042-test-mission-implement-WP02.md",
"reason": null,
"guard_failures": [],
"progress": {
"total_wps": 5,
"done_wps": 1,
"approved_wps": 0,
"in_progress_wps": 1,
"planned_wps": 3,
"for_review_wps": 0
},
"run_id": "abc123",
"step_id": "implement",
"decision_id": null,
"question": null,
"options": null
}
Guards block step transitions by returning failure descriptions:
| Guard | Syntax | Checks |
|---|---|---|
artifact_exists | artifact_exists("spec.md") | File exists relative to mission dir |
gate_passed | gate_passed("review_gate") | Gate event in mission-events.jsonl |
all_wp_status | all_wp_status("approved_or_done") | All WPs in a specific lane or named accepted-ready set |
any_wp_status | any_wp_status("for_review") | At least one WP in lane |
input_provided | input_provided("architecture") | Input exists in runtime model |
event_count | event_count("review", 1) | Minimum event count threshold |
Guards never raise exceptions — they return false on missing context.
The runtime generates a temp file at:
/tmp/spec-kitty-next-{agent}-{mission_slug}-{action}[-{wp_id}].md
Template actions (specify, plan, tasks): Mission context header + governance context + action-specific template content.
WP actions (implement, review): Full isolation-aware prompt containing:
tasks/WP##.md)Decision prompts: Question text, options, and the --answer command to run.
Runtime state is persisted between calls:
.kittify/runtime/
├── feature-runs.json # Index: {"mission-slug": {"run_id": "...", "run_dir": "..."}}
└── runs/
└── <run_id>/
└── state.json # Runtime snapshot (current step, inputs, etc.)
When --mission is omitted, the runtime detects the mission via (in order):
SPECIFY_MISSION environment variable###-mission-name)NOTE: Always use --mission <slug> in multi-mission repositories.
The runtime-next loop should load doctrine context iteratively — not all at once. Each step boundary is a context loading opportunity.
At the start of a session, resolve the active agent profile. This scopes your role, boundaries, and initialization context.
Load the profile using the Python API — do NOT read YAML files directly:
from charter.activation.doctrine_service_builder import build_activation_aware_doctrine_service
service = build_activation_aware_doctrine_service(project_root)
# resolve_profile()'s specializes_from lineage traversal is a repository
# operation, not available on the filtered `agent_profiles` dict — reach it
# through the pinned lineage/mutation accessor:
repo = service.agent_profile_repository
profile = repo.resolve_profile("<profile-id>") # e.g. "implementer"
# Internalize identity — acknowledge this at session start
print(profile.initialization_declaration)
# Respect scope boundaries
profile.specialization.primary_focus # What you actively do
profile.specialization.avoidance_boundary # What you must NOT do
profile.collaboration.handoff_to # Roles to defer to when out of scope
# Load only the directives this profile references (same `service`, gated dict)
for ref in profile.directive_references:
directive = service.directives.get(f"DIRECTIVE_{ref.code}")
Discovery (if you don't know your profile-id):
spec-kitty agent profile list
spec-kitty agent profile show <profile-id>
At each step boundary (when spec-kitty next returns a step decision),
load governance context scoped to the current action — not the full doctrine:
# Load only what's relevant to this action (compact after first load)
spec-kitty charter context --action implement --json
The context system uses two depth levels:
| Depth | When | Content |
|---|---|---|
bootstrap (depth-2) | First load for this action | Full policy summary + reference list |
compact (depth-1) | Subsequent loads | Resolved paradigms, directives, tools only |
First-load state is tracked per action in
.kittify/charter/context-state.json. This means implement and
review each get their own first-load bootstrap independently.
When you need governance guidance mid-step (e.g., how to structure tests, which review criteria apply), pull the specific tactic or directive by ID rather than re-loading the full context:
from charter.activation.doctrine_service_builder import build_activation_aware_doctrine_service
service = build_activation_aware_doctrine_service(project_root)
# Pull a specific tactic when it becomes relevant
tactic = service.tactics.get("tdd-red-green-refactor")
# Pull a specific directive
directive = service.directives.get("TEST_FIRST")
The action index (actions/<action>/index.yaml) tells you which doctrine
artifacts are relevant to the current step. Load the index to discover what
to pull:
from charter.offering.missions.action_index import load_action_index
index = load_action_index(missions_root, "software-dev", "implement")
# index.directives → ["TEST_FIRST", ...]
# index.tactics → ["tdd-red-green-refactor", ...]
# index.procedures → [...]
Do NOT load all doctrine into context at session start. This wastes tokens and dilutes relevance. Instead:
charter context --action <action>.Before invoking the runtime, gather the current state.
Commands:
# Check WP status for a mission
spec-kitty agent tasks status --mission <mission-slug>
# Check current context for an action
spec-kitty agent context resolve --action implement --mission <mission-slug> --json
What to look for:
# Run the next step
spec-kitty next --agent <agent> --mission <mission-slug> --json
# After completing a step successfully
spec-kitty next --agent <agent> --mission <mission-slug> --result success --json
# After a step failed
spec-kitty next --agent <agent> --mission <mission-slug> --result failed --json
# After a step was blocked
spec-kitty next --agent <agent> --mission <mission-slug> --result blocked --json
Note:
--missionis the sole selector. The legacy--featurealias has been removed (#1060); passing--featurenow exits withNo such option.
The --result flag tells the runtime the outcome of the previous step.
If omitted, spec-kitty next returns current state without advancing (query mode).
It does not report success for the previous step.
See references/runtime-result-taxonomy.md for the complete taxonomy.
| Kind | Next Action |
|---|---|
step | Read and execute prompt_file (always non-empty and resolvable on disk) |
decision_required | Answer with --answer and --decision-id |
blocked | Read reason + guard_failures, resolve blockers |
terminal | Run /spec-kitty.accept for final validation, then merge if acceptance passes |
Always check guard_failures — this field may appear on any decision kind,
not just blocked.
The kind="step" prompt-file contract is a hard runtime invariant (C1/C2).
A kind="step" envelope MUST carry a prompt_file (or its consumer-side
prompt_path alias) that is non-null, non-empty, and resolves on disk. If
the runtime cannot produce an actionable step (no composed action, guard
failure, blocked dependency, prompt build error, etc.), it returns
kind="blocked" with a non-empty reason (and optional machine-readable
code such as no_prompt_template). There is no third state: an agent loop
should never observe a kind="step" decision with prompt_file == null.
Always check progress for completion. If progress.done_wps equals
progress.total_wps but kind is not terminal, the mission is actually
complete (known issue #335). The runtime may not detect completion when no
prior run state exists. Treat this as terminal and run /spec-kitty.accept;
if acceptance passes, run /spec-kitty.merge, then run mission review and the
retrospective workflow.
When the runtime needs input:
# The decision includes question, options, and decision_id
# Answer using:
spec-kitty next --agent <agent> --mission <mission-slug> \
--result success --answer "<choice>" --decision-id "<decision_id>" --json
If the agent cannot determine the answer, escalate to the user with the question and options.
See references/blocked-state-recovery.md for detailed recovery patterns.
Quick diagnostic:
# Check WP status and dependency graph
spec-kitty agent tasks status --mission <mission-slug>
# Check specific WP dependencies
spec-kitty agent tasks list-dependents WP## --mission <mission-slug>
Common blockers:
| Blocker | Recovery |
|---|---|
| Missing artifacts (spec.md, plan.md) | Run the planning workflow first |
| Upstream WP not done | Implement or review the upstream WP |
| Review feedback not addressed | Re-implement, address feedback, move to for_review |
| Stale agent (WP in doing, no activity) | Move WP to planned with --force |
| Circular dependencies | Break cycle in WP frontmatter, re-run finalize-tasks |
The complete agent loop pattern:
# 1. Start the loop
DECISION=$(spec-kitty next --agent claude --mission 042-mission --json)
KIND=$(echo "$DECISION" | jq -r '.kind')
# 2. Loop until terminal or unresolvable block
while [ "$KIND" = "step" ] || [ "$KIND" = "decision_required" ]; do
# Workaround #335: check progress for completion even if kind != terminal
DONE=$(echo "$DECISION" | jq -r '.progress.done_wps // 0')
TOTAL=$(echo "$DECISION" | jq -r '.progress.total_wps // 0')
if [ "$TOTAL" -gt 0 ] && [ "$DONE" -eq "$TOTAL" ]; then
break # Mission is actually complete
fi
if [ "$KIND" = "step" ]; then
PROMPT=$(echo "$DECISION" | jq -r '.prompt_file')
# Contract (C1/C2, post-#336 fix): kind=step always carries a
# non-empty prompt_file resolvable on disk. If a prompt cannot be
# resolved, the runtime emits kind=blocked with a populated reason.
# Read and execute the prompt...
RESULT="success" # or "failed" or "blocked"
elif [ "$KIND" = "decision_required" ]; then
# Answer the question...
RESULT="success"
fi
DECISION=$(spec-kitty next --agent claude --mission 042-mission --result "$RESULT" --json)
KIND=$(echo "$DECISION" | jq -r '.kind')
done
# 3. Handle terminal state — canonical post-merge sequence
if [ "$KIND" = "terminal" ] || [ "$DONE" -eq "$TOTAL" ]; then
# Run /spec-kitty.accept.
# If acceptance passes, run /spec-kitty.merge.
# After merge, follow the canonical post-merge sequence:
# a. Mission review: /spec-kitty-mission-review
# b. Author or verify retrospective:
# spec-kitty retrospect create --mission 042-mission # if record absent
# OR verify: cat .kittify/missions/<mission_id>/retrospective.yaml
# c. Surface findings:
# spec-kitty retrospect summary # read-only aggregation
# spec-kitty agent retrospect synthesize --mission 042-mission # dry-run by default; --apply to mutate
# Note: summary aggregates; synthesize applies proposals — neither authors records.
fi
The loop continues until:
terminal — mission complete, exit loopquery — read-only preview, no state mutationblocked — cannot proceed without external resolutiondecision_required — only if the agent cannot answer (escalate to user)spec-kitty next rather than manually sequencing phases--mission in multi-mission repositoriesprompt_file — it contains the full context the agent needsguard_failures on every decision, not just blocked ones#335 — Completed missions return step instead of terminal. When
spec-kitty next is called on a mission with all WPs done but no prior
runtime run state, it creates a new run starting at discovery instead of
recognizing the mission is complete. Workaround: Check
progress.done_wps == progress.total_wps as a secondary completion signal.
#336 — fixed. prompt_file is always non-empty and resolvable on disk
on kind: step decisions. When no prompt is available, the runtime now emits
a structured kind: blocked decision with a non-empty reason (and optional
machine-readable code such as no_prompt_template). Agent loops no longer
need to defensively null-check prompt_file; a kind: step decision with a
null prompt is a runtime bug.
Not all governed work happens inside an active mission. When a user asks for
help with a task that has no active spec-kitty next loop — a code review, a
quick implementation, an ad-hoc analysis — you should still invoke Spec Kitty's
governance layer with standalone dispatch.
Spec Kitty never spawns a parallel LLM call. You are the host; Spec Kitty routes, assembles governance context, and records the trail.
If the user says anything like "use spec kitty to ...", "hey spec kitty ...", or "spec kitty ", run standalone dispatch unless they are clearly asking for a full mission.
Get context:
spec-kitty dispatch "implement the login handler" --json
spec-kitty dispatch "review WP05" --profile reviewer --json
Response includes invocation_id, governance_context_text, and governance_context_available.
Inject governance:
Read governance_context_text and treat it as binding governance context for your task. Follow any directives and constraints it contains.
If governance_context_available is false, note this to the user but proceed with the task.
Execute: Do the work. Generate the code, analysis, or plan.
Close the Op (mandatory — dispatch leaves it open):
spec-kitty profile-invocation complete \
--invocation-id <invocation_id> \
--outcome <done|failed|abandoned>
Use the real outcome: done for completed work, failed for work that did
not succeed, abandoned for dropped work. Never leave an Op open
deliberately — spec-kitty doctor ops reports and sweeps orphans.
Every standalone invocation writes a Tier 1 JSONL file to:
kitty-ops/<invocation_id>.jsonl
Viewable at any time with spec-kitty invocations list --json. No SaaS connection required.
For full CLI surface documentation, see src/charter/offering/skills/spec-kitty/SKILL.md.
references/runtime-result-taxonomy.md -- Decision kinds, output fields, and precedence rulesreferences/blocked-state-recovery.md -- 6 blocked state patterns with diagnosis and recoveryPublished 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.