Install any skill in seconds. Free to start, no credit card required.
Get Started Free →하네스를 구성합니다. 전문 에이전트를 정의하며, 해당 에이전트가 사용할 스킬을 생성하는 메타 스킬. (1) '하네스 구성해줘', '하네스 구축해줘' 요청 시, (2) '하네스 설계', '하네스 엔지니어링' 요청 시, (3) 새로운 도메인/프로젝트에 대한 하네스 기반 자동화 체계를 구축할 때, (4) 하네스 구성을 재구성하거나 확장할 때, (5) '하네스 점검', '하네스 감사', '하네스 현황', '에이전트/스킬 동기화' 등 기존 하네스 운영/유지보수 요청 시 사용.
SkillScore77/100
Test results 77
3/3 safety checks passed
14%77%of test cases passed +64 pts
Passed 17 of 22 test cases with the skill, and 3 of 22 without it.
14 fixed3 passed either way5 still failing0 broke
This benchmark measured an earlier version of the skill.
A newer attempt on gemini-3.6-flash on 10/2/2026 did not produce a publishable comparison (graded differently). The snapshot above is the previously measured run.
One test task사용자 피드백을 받아 QA 에이전트를 추가하고 스킬 톤을 보완했습니다. CLAUDE.md의 변경 이력을 수록할 마크다운 테이블 표준 형식을 보여줘.
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add revfactory-harness
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("revfactory-harness")
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 revfactory-harnessThe 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/revfactory-harness/SKILL.md https://app.decimal.ai/s/revfactory-harness/SKILL.md.claude/skills/revfactory-harness/SKILL.mdThis gets SKILL.md only. The skill's 9 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 revfactory-harnessimport 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("revfactory-harness")
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/revfactory-harness/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessfrom 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessimport 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessimport 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessfrom 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessfrom 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessimport 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("revfactory-harness")
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/revfactory-harness/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 9 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 revfactory-harnessfrom 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessfrom 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessimport 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessimport 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("revfactory-harness")
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/revfactory-harness/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessfrom 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("revfactory-harness")
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/revfactory-harness/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/revfactory-harness/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 9 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 revfactory-harnessNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/revfactory-harness/SKILL.md https://app.decimal.ai/s/revfactory-harness/SKILL.md.agents/skills/revfactory-harness/SKILL.mdThis gets SKILL.md only. The skill's 9 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 9 other files are not included.
Raw files: /s/revfactory-harness/SKILL.md · /s/revfactory-harness.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/revfactory-harness/SKILL.mdcurl -fsSL https://app.decimal.ai/s/revfactory-harness.jsonThis gets SKILL.md only. The skill's 9 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.
프로젝트에 맞는 하네스를 설계한다. 각 에이전트의 역할을 정의하고, 에이전트가 작업할 때 따를 스킬을 만든다.
프로젝트/.claude/agents/에, 스킬은 프로젝트/.claude/skills/에 만든다. 에이전트에는 누가 일하는지를, 스킬에는 그 일을 어떻게 하는지를 적는다.CLAUDE.md에 호출 조건과 변경 이력만 기록한다.CLAUDE.md에 계속 반영한다. 회고하고 변경 사항을 찾아내는 작업은 harness:evolve 스킬이 맡는다.CLAUDE.md 기록은 사용자가 대화에 쓰는 언어로 작성한다. 이 스킬 문서와 references/의 템플릿이 한국어로 쓰였다는 이유로 산출물을 한국어로 쓰지 않는다. 템플릿의 제목과 예시 문구도 그 언어로 옮긴다. 사용자가 언어를 따로 정하면 그 언어를 따르고, 따로 정하지 않은 채 기존 하네스를 확장하면 기존 파일의 언어를 따른다.하네스 스킬을 불러오면 기존 구성을 먼저 확인한다.
프로젝트/.claude/agents/, 프로젝트/.claude/skills/, 프로젝트/CLAUDE.md를 읽는다.
현재 상태에 따라 진행할 절차를 고른다.
| 변경 내용 | 1단계 | 2단계 | 3단계 | 4단계 | 5단계 | 6단계 |
|---|---|---|---|---|---|---|
| 에이전트 추가 | 생략하고 0단계 결과 사용 | 어떤 실행 모드에서 어느 팀과 단계에 둘지만 결정 | 필수 | 전용 스킬이 필요할 때 | 오케스트레이터 수정 | 필수 |
| 스킬 추가·수정 | 생략 | 생략 | 생략 | 필수 | 연결이 바뀔 때 | 필수 |
| 구조·실행 모드 변경 | 생략 | 필수 | 영향을 받는 에이전트만 | 영향을 받는 스킬만 | 필수 | 필수 |
기존 오케스트레이터에 TeamCreate, TeamDelete, CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS가 있으면 v1 산출물이다. 현재 실행 환경에서는 작동하지 않으므로 v2로 옮기자고 제안한다. 자세한 방법은 references/execution-modes.md의 「v1에서 v2로 전환」을 따른다.
실제 에이전트·스킬 목록과 CLAUDE.md 기록을 대조해 불일치를 찾는다.
점검 결과와 실행 계획을 사용자에게 알리고 확인받는다.
Harness v2는 Claude Code의 멀티에이전트 기능 세 가지를 사용한다. 작업 흐름에 맞춰 다음 모드 가운데 하나를 고른다.
| 실행 모드 | 사용하는 기능 | 알맞은 작업 |
|---|---|---|
| 워크플로 조율 | Workflow 스크립트의 agent(), pipeline(), parallel(), phase() | 처리 목록, 검증 절차, 반복 횟수를 코드로 정할 수 있는 작업. 스키마에 맞춘 결과가 필요하거나 Agent를 수십 번 이상 호출해야 하는 작업 |
| 지속형 에이전트 협업 | Agent(name:), SendMessage, TaskCreate, TaskUpdate | 이름 있는 전문가가 대화 맥락을 유지하면서 피드백·협상·공동 편집을 반복해야 하는 작업 |
| 서브에이전트 위임 | Agent 한 번 호출. 기본적으로 백그라운드에서 실행하며 병렬 호출 가능 | 에이전트끼리 대화할 필요가 없고 결과만 한 번 받으면 되는 작업 |
다음 순서로 결정한다.
Workflow 도구를 쓰려면 사용자가 명시적으로 동의해야 한다. 사용자가 직접 워크플로 실행을 요청했거나, Workflow 호출을 지시하는 오케스트레이터 스킬을 사용자가 불러왔다면 동의한 것으로 본다. 기본 실행은 에이전트 몇 명으로 제한하고, 사용자가 "철저히", "전수"처럼 넓은 조사를 요구했을 때만 대규모로 늘린다.
실행 모드 비교와 동시 실행 상한, 스키마, 토큰 예산, 재개 조건은
references/execution-modes.md에서 확인한다.
references/team-patterns.md에 있다.
pipeline()에 알맞다.pipeline()과 필요할 때만 parallel()을 쓴다.confirmed로 판정한 항목만 통과시킨다. refuted나 uncertain 판정은 통과로 세지 않는다.필요한 전문 지식, 병렬 처리 가능 여부, 유지해야 할 대화 맥락, 다시 쓸 가능성을 기준으로 에이전트를 나눈다. 자세한 표는 references/team-patterns.md의 「에이전트 분리 기준」에서 확인한다.
여러 세션에서 재사용할 전문 에이전트는 프로젝트/.claude/agents/{name}.md 파일로 정의한다. 반복해서 사용할 역할을 Agent 도구의 prompt에만 직접 넣지 않는다.
Agent 도구에서는 subagent_type: "{name}", Workflow에서는 agentType: "{name}"으로 부른다.재사용할 전문가 역할은 사용자 정의 유형으로 파일에 만들고, 호출할 때 그 파일의 이름을 subagent_type이나 agentType에 지정한다. general-purpose, Explore, Plan 같은 기본 제공 유형을 그대로 쓰는 단발 작업에는 별도 정의 파일을 만들지 않는다.
새 에이전트 파일을 만들기 전에 프로젝트/.claude/agents/의 기존 에이전트와 역할이 겹치는지 확인한다. 1단계를 생략하고 에이전트만 추가할 때도 이 확인은 건너뛰지 않는다. 하네스를 여러 번 구축하거나 확장하면 같은 역할의 에이전트가 이름만 달리해 쌓일 수 있기 때문이다. 겹치면 새 이름으로 만들지 말고 기존 에이전트를 그대로 쓰거나 확장한다. 판단 기준과 예외(도메인을 의도적으로 특화한 경우)는 references/team-patterns.md의 「에이전트 재사용 설계」에서 확인한다.
업무의 복잡도, 작업 기간, 자율성, 응답 속도를 기준으로 에이전트마다 모델을 고른다. YAML 프론트매터(머리말)의 model:이나 호출 인자인 model, opts.model에 지정하고, 선택 이유를 에이전트 정의나 오케스트레이터에 주석으로 남긴다.
| 모델 | 선택 기준 | 대표 업무 |
|---|---|---|
| fable | 스스로 계획하고 여러 단계를 연결해 장기간 자율적으로 실행해야 하는 최고 난도 업무 | 에이전트 조율, 계획 수립과 장기 실행, 방대한 자료 통합, 막연한 아이디어 구체화 |
| opus | 범위는 분명하지만 깊은 추론과 분석이 필요한 전문 업무 | 설계·아키텍처, 코드 생성, 복잡한 분석, 교차 검증, 연구 방법 비판, 창작 |
| sonnet | 절차가 분명하고 빠른 처리가 중요한 일상 업무 | 로그 분석, 형식 변환, 정적 파일 검사, 배포 스크립트 실행, 단순 수집, 일반 글쓰기·요약 |
모델별 자세한 기준은
references/model-selection-guide.md에서 확인한다.
YAML 프론트매터에는 name과 description을 반드시 넣는다. 필요하면 사용할 도구를 제한하는 tools와 모델을 바꾸는 model을 추가한다. 읽기 전용 검토·분석 에이전트의 tools에서는 Edit와 Write를 빼서 파일을 바꾸지 못하게 한다.
반대로 산출물을 고치는 에이전트에는 Write와 함께 Edit도 준다. Edit가 없으면 한 줄을 고칠 때도 파일 전체를 다시 써야 하므로, 산출물이 크면 에이전트가 수정을 포기하고 우회한다. 또 tools에 적은 도구가 실행할 때 주어지지 않은 사례가 있으므로, 지속형 에이전트에게는 첫 보고에서 실제로 쓸 수 있는 도구 목록을 알리게 한다.
본문에는 핵심 역할, 작업 원칙, 입력·출력 규칙, 오류 처리, 협업 방법을 반드시 적는다. 지속형 에이전트에는 ## 통신 규칙을 추가해 SendMessage를 주고받을 대상과 공유 작업 목록 사용법을 정한다.
정의 템플릿, 전체 예시,
tools를 제한할 때 주의할 점은references/team-patterns.md의 「에이전트 정의 구조」에서 확인한다.
Explore는 읽기 전용이라 검증 스크립트를 실행할 수 없다.references/qa-agent-guide.md를 따른다.각 에이전트가 따를 스킬을 프로젝트/.claude/skills/{name}/SKILL.md에 만든다. 자세한 작성법은 references/skill-writing-guide.md를 따른다.
새 스킬을 만들기 전에 프로젝트/.claude/skills/의 기존 스킬과 기능이 겹치는지 확인한다. 겹치면 새 이름으로 만들지 말고 기존 스킬을 에이전트에 연결하거나 확장한다. 판단 기준과 예외(도메인을 의도적으로 특화한 경우), 어디까지 일반화할지는 references/skill-writing-guide.md의 「스킬 재사용 설계」에서 확인한다.
skill-name/
├── SKILL.md # 필수
│ ├── YAML 프론트매터 # name과 description 필수
│ └── Markdown 본문
├── scripts/ # 선택: 반복하거나 결과가 항상 같아야 하는 작업의 실행 코드
├── references/ # 선택: 필요할 때만 읽는 참조 문서
└── assets/ # 선택: 템플릿, 이미지처럼 산출물에 쓰는 파일
Claude는 스킬의 name과 description을 보고 어떤 스킬을 불러올지 판단한다. 이 가운데 description에는 스킬이 하는 일과 사용해야 하는 상황을 구체적으로 적고, 비슷해 보이지만 사용하면 안 되는 경우도 구분한다.
나쁜 예: "PDF 문서를 처리하는 스킬"
좋은 예: "PDF 파일 읽기, 텍스트·표 추출, 병합, 분할, 회전, 워터마크, 암호화, OCR 등 PDF 작업을 수행한다. 사용자가 .pdf 파일을 언급하거나 PDF 산출물을 요청하면 반드시 사용한다."
| 원칙 | 적용 방법 |
|---|---|
| 이유부터 설명한다 | ALWAYS, NEVER만 나열하지 말고 왜 필요한 규칙인지 밝힌다. 이유를 알아야 예외 상황에서도 올바르게 판단할 수 있다. |
| 간결하게 쓴다 | SKILL.md는 500줄 미만으로 유지한다. 판단에 도움이 되지 않는 내용은 지우거나 references/로 옮긴다. |
| 원리로 일반화한다 | 특정 예시에만 맞는 규칙을 만들지 않는다. 여러 입력에 적용할 수 있는 판단 기준을 적는다. |
| 반복 코드는 미리 넣는다 | 테스트할 때 여러 에이전트가 같은 스크립트를 다시 작성한다면 scripts/에 넣는다. |
| 지시문으로 쓴다 | ~한다나 ~하라 가운데 문서에 맞는 한 가지 어미를 골라 통일한다. 해야 할 행동이 분명하게 드러나야 한다. |
스킬은 필요한 정보와 실행 코드를 다음 시점에 불러온다.
| 정보 | 불러오는 시점 | 권장 분량 |
|---|---|---|
메타데이터(name, description) | 항상 | 약 100단어 |
SKILL.md 본문 | 스킬을 불러올 때 | 500줄 미만 |
references/ | 해당 자료가 필요할 때 | 제한 없음 |
scripts/ | 반복 작업이나 결과가 항상 같아야 하는 작업을 실행할 때 | 제한 없음. 내용을 읽지 않고 바로 실행할 수 있음 |
SKILL.md가 500줄에 가까워지면 세부 내용을 references/로 옮기고, 본문에는 언제 어떤 파일을 읽을지 적는다.오케스트레이터도 스킬이다. 개별 에이전트와 스킬을 하나의 작업 흐름으로 묶고, 누가 언제 어떤 순서로 협업하는지 정한다. 모드별 전체 템플릿은 references/orchestrator-template.md, 워크플로 스크립트 예시는 references/workflow-recipes.md에 있다.
기존 하네스를 확장할 때는 오케스트레이터를 새로 만들지 말고 기존 파일을 고친다. 에이전트를 추가하면 구성, 작업 배정, 데이터 전달 순서에 반영하고 description에도 새 호출 조건을 넣는다.
A. 워크플로 조율
오케스트레이터 스킬에 Workflow 스크립트를 정의한다. 스크립트는 meta, phase(), pipeline(), parallel(), agent()로 구성한다. 사용자 정의 유형은 agentType으로 지정하고, 스키마에 맞춘 결과는 schema로 받는다.
[오케스트레이터 스킬] → Workflow(script)
├── phase('수집'): pipeline(items, ...) ← 미리 정한 목록을 분산 처리
├── phase('검증'): 적대적 검증 또는 심사위원단
└── return 구조화된 결과 → 메인이 종합 보고서 작성
B. 지속형 에이전트 협업
이름 있는 에이전트를 실행한 뒤 공유 작업 목록과 SendMessage로 조율한다. TeamCreate와 TeamDelete는 더 이상 없다. 명시적인 팀 객체를 만들지 않으며, 세션에서 이름을 붙여 실행한 에이전트는 자동으로 구성되는 하나의 협업 그룹에 속한다. 해당 에이전트에는 이전 대화 맥락을 유지한 채 다시 메시지를 보낼 수 있다.
[메인 에이전트(리더)]
├── Agent(name: "researcher", ...) / Agent(name: "critic", ...) ← 병렬 실행
├── TaskCreate(작업 + 의존 관계)
├── SendMessage({to: "critic"}, "researcher의 초안을 검토하라")
└── 결과 수집 및 종합
C. 서브에이전트 위임
메시지 한 번에 Agent 도구를 N번 병렬로 호출하고 완료 알림에서 결과를 모은다. 호출한 에이전트는 기본적으로 백그라운드에서 실행된다.
단계마다 작업 성격이 다르면 혼합 모드로 구성할 수 있다. 예를 들어 워크플로로 자료를 모은 뒤 지속형 에이전트가 합의해 통합하거나, 지속형 에이전트가 만든 결과를 워크플로로 적대적 검증할 수 있다. 각 단계 위에 **실행 모드:**를 적는다.
| 방법 | 구현 | 알맞은 실행 모드 | 사용할 때 |
|---|---|---|---|
| 구조화된 반환값 | Workflow의 agent(prompt, {schema})가 검증된 JSON 반환 | 워크플로 조율 | 다음 단계가 결과를 코드로 처리해야 할 때 |
| 일반 반환값 | Agent 도구의 반환 메시지 | 서브에이전트 | 메인이 요약 결과를 직접 모을 때 |
| 메시지 | SendMessage로 에이전트끼리 직접 전달 | 지속형 에이전트 | 실시간 조율과 피드백이 필요할 때 |
| 공유 작업 목록 | TaskCreate, TaskUpdate로 상태 공유 | 지속형 에이전트 | 진행 상황, 의존 관계, 동적 배정을 관리할 때 |
| 파일 | 정해 둔 경로에 쓰고 읽기 | 모든 모드 | 데이터가 크거나 나중에 작업 과정을 확인해야 할 때 |
파일로 전달할 때는 다음 규칙을 지킨다.
_workspace/에 중간 산출물을 저장한다.{phase}_{agent}_{artifact}.{ext} 형식을 쓴다. 예: 01_analyst_requirements.md_workspace/는 사후 검증을 위해 남긴다.오케스트레이터에 오류 처리 방침을 넣는다.
agent()는 null을 반환하고 parallel()은 실패를 예외로 던지지 않는다. 결과 배열에 .filter(Boolean)을 적용하고 빠진 항목 수를 log()로 알려야 한다.SendMessage로 상태를 확인하고 다시 지시한다. 그래도 실패하면 같은 사용자 정의 유형을 새 이름으로 실행하고, 필요한 작업 맥락을 프롬프트로 넘긴다.오류 유형별 대응 방법은
references/orchestrator-template.md에서 해당 실행 모드 템플릿의 「오류 처리」를 확인한다.
| 작업 규모 | 지속형 에이전트 수 | 워크플로의 Agent 호출 규모 |
|---|---|---|
| 소규모: 작업 10개 미만 | 2~3명 | 2~5건 |
| 중규모: 작업 10~20개 | 3~5명 | 약 10건. 동시 실행 상한을 넘으면 자동 대기 |
| 대규모: 작업 20개 초과 | 감독자 + 작업자 3~5명 | 수십~수백 건. 전체 상한 1,000건 |
+500k처럼 토큰 예산을 지정하면 워크플로 스크립트에서 budget.remaining()을 확인해 실행 규모를 조절한다.CLAUDE.md에 하네스 연결 정보 기록구성을 마치면 프로젝트의 CLAUDE.md에 하네스가 있다는 사실과 호출 조건을 기록한다. CLAUDE.md는 새 세션마다 읽히므로 자세한 실행 규칙을 반복해서 넣지 않는다.
## 하네스: {도메인명}
**목표:** {하네스의 핵심 목표 한 줄}
**호출 조건:** {도메인} 관련 작업을 요청받으면 `{orchestrator-skill-name}` 스킬을 사용한다. 단순 질문에는 직접 답해도 된다.
**변경 이력:**
| 날짜 | 변경 내용 | 대상 | 사유 |
| --- | --- | --- | --- |
| {YYYY-MM-DD} | Harness v2로 처음 구성 | 전체 | - |
에이전트·스킬 목록, 디렉터리 구조, 자세한 실행 규칙은 넣지 않는다. 이 정보는 오케스트레이터 스킬과 .claude/agents/, .claude/skills/에서 관리한다. CLAUDE.md에는 호출 조건과 변경 이력만 둔다.
오케스트레이터는 처음 실행할 때뿐 아니라 결과를 다시 고칠 때도 작동해야 한다.
description에 다시 실행, 재실행, 업데이트, 수정, 보완, {도메인}의 {부분 작업}만 다시, 이전 결과를 바탕으로, 결과 개선 같은 표현을 넣는다._workspace/가 있고 일부만 고쳐 달라는 요청이면 해당 단계나 에이전트만 다시 실행한다._workspace/가 있고 새 입력을 받았으면 기존 디렉터리를 타임스탬프가 붙은 디렉터리로 옮긴 뒤 새로 실행한다._workspace/가 없으면 처음부터 실행한다.runId가 있으면 resumeFromRunId로 재개할 수 있다. 바뀌지 않은 agent() 호출은 캐시 결과를 사용한다.생성한 하네스를 검증한다. 자세한 방법은 references/skill-testing-guide.md를 따른다.
name과 description이 있는지 확인한다..claude/commands/에 명령 파일을 만들지 않았는지 확인한다.TeamCreate, TeamDelete, team_name, 실험 기능 플래그가 남지 않았는지 확인한다.meta가 값만 담은 리터럴인지, Date.now()와 Math.random()을 쓰지 않았는지, 전체 결과를 기다려야 할 때만 parallel()을 썼는지, .filter(Boolean)이 빠지지 않았는지, phase() 제목이 meta.phases와 일치하는지 확인한다.SendMessage의 발신·수신 경로, 작업 의존 관계, 에이전트 수를 확인한다.scripts/에 넣는다.명백히 무관한 요청은 경계를 검증하지 못한다. 예를 들어 이미지 생성 스킬을 시험할 때 피보나치 함수 작성보다 이 엑셀 파일의 차트를 PNG로 추출해 줘가 더 좋은 경계 사례다. 결과는 이미지지만 실제로는 스프레드시트 도구가 더 알맞기 때문이다. 기존 스킬과 호출 조건이 겹치는지도 확인한다.
오케스트레이터 스킬에 ## 테스트 시나리오를 만들고 정상 흐름 한 가지와 오류 흐름 한 가지 이상을 적는다.
하네스는 한 번 만들고 끝나는 산출물이 아니다.
실행 결과를 회고하고 피드백을 반영하는 작업은 harness:evolve 스킬이 맡는다. 사용자가 하네스 회고, 하네스 진화, 피드백 반영해줘라고 요청하면 harness:evolve를 사용한다. 이 스킬은 처음 구성과 현재 상태의 차이를 분석하고, 여러 상황에 적용할 수 있도록 피드백을 정리해 에이전트·스킬·오케스트레이터에 반영한다. CLAUDE.md 변경 이력도 갱신한다.
이 harness 스킬은 기존 하네스를 운영하고 유지 보수하는 다음 절차를 직접 처리한다.
.claude/agents/, .claude/skills/, 오케스트레이터 구성을 비교해 불일치 목록을 만들고 사용자에게 알린다.CLAUDE.md에 날짜, 변경 내용, 대상, 사유를 적는다.CLAUDE.md와 실제 파일이 일치하는지 마지막으로 확인한다.다음 상황에서는 harness:evolve로 개선하자고 제안한다.
프로젝트/.claude/agents/에 재사용할 모든 사용자 정의 유형의 파일을 만들었다. 단발 작업에 기본 제공 유형을 그대로 쓰는 경우는 제외했다.프로젝트/.claude/skills/에 필요한 SKILL.md와 참조 문서를 만들었다.model:을 복잡도, 작업 기간, 자율성, 응답 속도에 따라 골랐고 이유를 주석으로 남겼다. 모든 에이전트에 같은 고성능 모델을 일괄 지정하지 않았다.TeamCreate, TeamDelete, 실험 기능 플래그 같은 v1 방식이 남지 않았다..filter(Boolean)을 넣고 meta에는 리터럴만 썼다. 꼭 필요할 때만 parallel()로 전체 결과를 기다린다..claude/commands/에 파일을 만들지 않았다.CLAUDE.md 기록을 사용자가 대화에 쓰는 언어로 작성했다. 사용자가 따로 정한 언어나 기존 하네스 파일의 언어가 있으면 그 언어를 따랐다.description에 해야 할 일과 호출 조건을 구체적으로 적고 후속 요청 표현도 넣었다.SKILL.md 본문이 500줄 미만이다. 500줄 이상이면 세부 내용을 references/로 옮겼다.CLAUDE.md에 호출 조건과 변경 이력만 기록했다.references/execution-modes.mdreferences/model-selection-guide.mdreferences/team-patterns.mdreferences/team-examples.mdreferences/workflow-recipes.mdreferences/orchestrator-template.mdreferences/skill-writing-guide.mdreferences/skill-testing-guide.mdreferences/qa-agent-guide.mdPublished 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.