Use when long-lived agents, project memories, system prompts, or playbooks are repeatedly summarized, rewritten, or optimized and risk losing domain detail, provenance, or execution learnings.
日本語の概要は準備中です。原文の説明を表示しています。
Also use for agentic data engineering pipelines, code generation agents, agent-powered CLI tools, MCP server development, or any system where an AI model calls tools, makes decisions, or loops
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Build agents that are robust, observable, and actually finish the job. The difference between a demo and a production agent is: structured outputs, error recovery, observability, and a loop that terminates cleanly.
One LLM loop that calls tools until done. Best for well-scoped tasks.
User Request
→ Agent (LLM)
→ Tool calls (file read, API call, code exec, etc.)
→ More tool calls as needed
→ Final structured output
One orchestrator plans and delegates; subagents execute specialized tasks in parallel.
User Request
→ Orchestrator (plans, decomposes, synthesizes)
→ Subagent A: parse mapping files
→ Subagent B: generate SQL models
→ Subagent C: generate YAML metadata
→ Orchestrator aggregates + validates
→ Final output
Use this when tasks are genuinely parallelizable and have clear boundaries. Don't add subagents just to look architectural — coordination overhead is real.
Agent produces a structured plan first, then executes each step. Reduces hallucination on complex tasks because it commits to a strategy before acting.
User Request
→ Planning pass (output: list of steps)
→ Human review (optional)
→ Execution pass (follow the plan, step by step)
→ Validation
Tools should be narrow, deterministic, and easy to verify. An agent that has 3 sharp tools beats one with 15 blurry ones.
Anthropic tool schema:
tools = [
{
"name": "read_mapping_file",
"description": "Read an Informatica mapping JSON file and return its contents. Use this before any analysis or generation step.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "Absolute path to the mapping JSON or XML file"
}
},
"required": ["file_path"]
}
},
{
"name": "write_dbt_model",
"description": "Write a dbt model SQL file and its schema YAML. Call once per model.",
"input_schema": {
"type": "object",
"properties": {
"model_name": {"type": "string"},
"sql_content": {"type": "string"},
"schema_yaml": {"type": "string"},
"output_dir": {"type": "string"}
},
"required": ["model_name", "sql_content", "output_dir"]
}
}
]
Tool implementation:
import json
async def execute_tool(tool_name: str, tool_input: dict) -> str:
if tool_name == "read_mapping_file":
with open(tool_input["file_path"]) as f:
return f.read()
elif tool_name == "write_dbt_model":
path = f"{tool_input['output_dir']}/{tool_input['model_name']}.sql"
with open(path, "w") as f:
f.write(tool_input["sql_content"])
return json.dumps({"written": path, "status": "ok"})
else:
return json.dumps({"error": f"Unknown tool: {tool_name}"})
import anthropic
import json
from typing import Any
client = anthropic.AsyncAnthropic()
async def run_agent(
system: str,
user_message: str,
tools: list[dict],
max_iterations: int = 10,
) -> tuple[str, list[dict]]:
messages = [{"role": "user", "content": user_message}]
tool_calls_log = []
for iteration in range(max_iterations):
response = await client.messages.create(
model="claude-sonnet-4-6",
max_tokens=8096,
system=system,
tools=tools,
messages=messages,
)
# Append assistant response to message history
messages.append({"role": "assistant", "content": response.content})
# Done — no tool calls
if response.stop_reason == "end_turn":
final_text = next(
(block.text for block in response.content if hasattr(block, "text")), ""
)
return final_text, tool_calls_log
# Process tool calls
if response.stop_reason == "tool_use":
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = await execute_tool(block.name, block.input)
tool_calls_log.append({
"tool": block.name,
"input": block.input,
"result": result[:500], # truncate for logging
})
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
messages.append({"role": "user", "content": tool_results})
raise RuntimeError(f"Agent hit max iterations ({max_iterations}) without completing")
For agents that must return structured data (not just text), use either:
Option A: Force JSON in the prompt + parse
SYSTEM = """
You are a dbt generator. When done, you MUST output a single JSON object
(no markdown, no explanation) matching this schema:
{
"models": [{"name": str, "sql": str, "materialization": str}],
"sources_yaml": str,
"issues": [str]
}
"""
# Parse the final response
import json
result = json.loads(final_text)
Option B: Pydantic + instructor or LiteLLM
from pydantic import BaseModel
import litellm
class GeneratedProject(BaseModel):
models: list[DbtModel]
sources_yaml: str
issues: list[str]
response = await litellm.acompletion(
model="claude-sonnet-4-6",
messages=messages,
response_format=GeneratedProject,
)
project = GeneratedProject.model_validate_json(response.choices[0].message.content)
Option C: Final structured tool call — give the agent a submit_result tool with your schema. When the agent calls it, you have your structured output without parsing text.
{
"name": "submit_result",
"description": "Call this when you have finished generating all models. Submit the complete result.",
"input_schema": GeneratedProject.model_json_schema()
}
import asyncio
async def orchestrate_migration(mapping_files: list[str]) -> list[GeneratedProject]:
# Parse all mappings in parallel
parse_tasks = [
run_agent(PARSER_SYSTEM, f"Parse this mapping: {path}", parse_tools)
for path in mapping_files
]
parsed_results = await asyncio.gather(*parse_tasks)
# Generate dbt models in parallel
generate_tasks = [
run_agent(GENERATOR_SYSTEM, f"Generate dbt models for:\n{result}", generate_tools)
for result, _ in parsed_results
]
generated_results = await asyncio.gather(*generate_tasks)
# Validate all in a single pass
validation_input = "\n\n".join(r for r, _ in generated_results)
validated, _ = await run_agent(VALIDATOR_SYSTEM, validation_input, validate_tools)
return generated_results
Key principle: subagents should be stateless and receive all context they need in their initial message. Don't rely on shared state — pass data explicitly.
Retry with feedback:
async def run_agent_with_retry(
system: str,
user_message: str,
validate_fn: callable,
max_attempts: int = 3,
) -> Any:
last_error = None
for attempt in range(max_attempts):
result, _ = await run_agent(system, user_message, tools)
try:
validated = validate_fn(result)
return validated
except Exception as e:
last_error = e
# Feed the error back — agent learns from its mistake
user_message = (
f"{user_message}\n\n"
f"Previous attempt failed validation:\n{e}\n\n"
f"Previous output:\n{result}\n\n"
f"Please fix the issues and try again."
)
raise RuntimeError(f"Agent failed after {max_attempts} attempts: {last_error}")
Checkpoint / resume for long pipelines:
import json, os
def save_checkpoint(job_id: str, step: str, data: Any):
path = f".checkpoints/{job_id}/{step}.json"
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w") as f:
json.dump(data, f)
def load_checkpoint(job_id: str, step: str) -> Any | None:
path = f".checkpoints/{job_id}/{step}.json"
if os.path.exists(path):
with open(path) as f:
return json.load(f)
return None
# In the pipeline:
async def run_pipeline(job_id: str, mapping: dict):
parsed = load_checkpoint(job_id, "parsed")
if not parsed:
parsed, _ = await run_agent(PARSER_SYSTEM, str(mapping), parse_tools)
save_checkpoint(job_id, "parsed", parsed)
generated = load_checkpoint(job_id, "generated")
if not generated:
generated, _ = await run_agent(GENERATOR_SYSTEM, str(parsed), gen_tools)
save_checkpoint(job_id, "generated", generated)
import time, uuid
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class AgentRun:
run_id: str = field(default_factory=lambda: str(uuid.uuid4()))
started_at: str = field(default_factory=lambda: datetime.utcnow().isoformat())
steps: list[dict] = field(default_factory=list)
status: str = "running"
error: str | None = None
duration_ms: float = 0
def log_step(self, step_type: str, data: dict):
self.steps.append({
"type": step_type,
"timestamp": datetime.utcnow().isoformat(),
**data
})
def finish(self, status: str = "done", error: str | None = None):
self.status = status
self.error = error
Treat your agent like a function with inputs and expected outputs. Regression-test every change.
# evals/evals.json format
evals = [
{
"id": 1,
"prompt": "Convert the customer_orders mapping to dbt",
"expected": {
"model_count": 2,
"has_staging_model": True,
"incremental_strategy": "merge"
}
}
]
async def grade_run(prompt: str, expected: dict, agent_output: str) -> dict:
results = {}
# Programmatic checks
if "model_count" in expected:
import json
out = json.loads(agent_output)
results["model_count"] = len(out["models"]) == expected["model_count"]
if "has_staging_model" in expected:
results["has_staging_model"] = any(
m["name"].startswith("stg_") for m in json.loads(agent_output)["models"]
)
# LLM-as-judge for qualitative checks
judge_prompt = f"""
Expected behavior: {expected}
Agent output: {agent_output[:2000]}
Score each criterion 0-3 (0=missing, 1=poor, 2=ok, 3=excellent).
Return JSON: {{"scores": {{}}, "overall": 0-3, "reasoning": ""}}
"""
judge_response, _ = await run_agent(JUDGE_SYSTEM, judge_prompt, [])
results["llm_judge"] = json.loads(judge_response)
pass_rate = sum(1 for v in results.values() if v is True) / len(results)
return {"pass_rate": pass_rate, "details": results}
Build tools you can expose to Claude via MCP:
# mcp_server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
server = Server("my-agent-tools")
@server.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="parse_mapping",
description="Parse an Informatica mapping file and return structured metadata",
inputSchema={
"type": "object",
"properties": {
"file_path": {"type": "string"}
},
"required": ["file_path"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "parse_mapping":
result = await parse_mapping_file(arguments["file_path"])
return [types.TextContent(type="text", text=json.dumps(result))]
raise ValueError(f"Unknown tool: {name}")
async def main():
async with stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
if __name__ == "__main__":
import asyncio
asyncio.run(main())
System prompt structure that works:
You are a [role]. Your job is to [goal].
## What you have access to
[tool list with when to use each]
## How to approach the task
1. First, [step]
2. Then, [step]
## Output format
[exact schema or template]
## Rules
[only the non-obvious ones — don't list obvious things like "be accurate"]
Don't over-constrain. A smart model given the right goal and tools will often find a better path than rigid step-by-step instructions. Explain the why — let the model reason.
Few-shot examples in the user message (not system) improve consistency on structured output without bloating the system prompt.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when long-lived agents, project memories, system prompts, or playbooks are repeatedly summarized, rewritten, or optimized and risk losing domain detail, provenance, or execution learnings.
日本語の概要は準備中です。原文の説明を表示しています。
Use this skill when the user explicitly asks to map, document, or onboard into an existing codebase. Trigger for prompts like "map this codebase", "document this architecture", "onboard me to this repo", or "create codebase docs". Do not trigger for routine feature implementation, bug fixes, or narrow code edits unless the user asks for repository-level discovery.
日本語の概要は準備中です。原文の説明を表示しています。
Adds educational comments to a code file so it becomes a learning resource, asking for the file (with a list of close matches) if none is given. Use when preparing code for learners, onboarding, or teaching.
日本語の概要は準備中です。原文の説明を表示しています。
Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate documents, layers, paths, text frames, colors, symbols, artboards, or any Illustrator DOM objects. Covers the complete JavaScript object model, coordinate system, measurement units, export workflows, and scripting best practices.
日本語の概要は準備中です。原文の説明を表示しています。
Patterns and techniques for adding governance, safety, and trust controls to AI agent systems. Use this skill when: - Building AI agents that call external tools (APIs, databases, file systems) - Implementing policy-based access controls for agent tool usage - Adding semantic intent classification to detect dangerous prompts - Creating trust scoring systems for multi-agent workflows - Building audit trails for agent actions and decisions - Enforcing rate limits, content filters, or tool restrictions on agents - Working with any agent framework (PydanticAI, CrewAI, OpenAI Agents, LangChain, AutoGen)
日本語の概要は準備中です。原文の説明を表示しています。
Check any AI agent codebase against the OWASP Agentic Security Initiative (ASI) Top 10 risks. Use this skill when: - Evaluating an agent system's security posture before production deployment - Running a compliance check against OWASP ASI 2026 standards - Mapping existing security controls to the 10 agentic risks - Generating a compliance report for security review or audit - Comparing agent framework security features against the standard - Any request like "is my agent OWASP compliant?", "check ASI compliance", or "agentic security audit"
日本語の概要は準備中です。原文の説明を表示しています。