Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 44 additions & 46 deletions skills/agent-builder/references/tool-templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
"input_schema": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The shell command to execute"
}
"command": {"type": "string", "description": "The shell command to execute"}
},
"required": ["command"],
},
Expand All @@ -37,13 +34,10 @@
"input_schema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path to the file"
},
"path": {"type": "string", "description": "Relative path to the file"},
"limit": {
"type": "integer",
"description": "Max lines to read (default: all)"
"description": "Max lines to read (default: all)",
},
},
"required": ["path"],
Expand All @@ -56,14 +50,8 @@
"input_schema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path for the file"
},
"content": {
"type": "string",
"description": "Content to write"
},
"path": {"type": "string", "description": "Relative path for the file"},
"content": {"type": "string", "description": "Content to write"},
},
"required": ["path", "content"],
},
Expand All @@ -75,18 +63,12 @@
"input_schema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path to the file"
},
"path": {"type": "string", "description": "Relative path to the file"},
"old_text": {
"type": "string",
"description": "Exact text to find (must match precisely)"
},
"new_text": {
"type": "string",
"description": "Replacement text"
"description": "Exact text to find (must match precisely)",
},
"new_text": {"type": "string", "description": "Replacement text"},
},
"required": ["path", "old_text", "new_text"],
},
Expand All @@ -104,9 +86,18 @@
"items": {
"type": "object",
"properties": {
"content": {"type": "string", "description": "Task description"},
"status": {"type": "string", "enum": ["pending", "in_progress", "completed"]},
"activeForm": {"type": "string", "description": "Present tense, e.g. 'Reading files'"},
"content": {
"type": "string",
"description": "Task description",
},
"status": {
"type": "string",
"enum": ["pending", "in_progress", "completed"],
},
"activeForm": {
"type": "string",
"description": "Present tense, e.g. 'Reading files'",
},
},
"required": ["content", "status", "activeForm"],
},
Expand Down Expand Up @@ -138,6 +129,7 @@
# TOOL IMPLEMENTATIONS
# =============================================================================


def safe_path(p: str) -> Path:
"""
Security: Ensure path stays within workspace.
Expand All @@ -164,12 +156,7 @@ def run_bash(command: str) -> str:

try:
result = subprocess.run(
command,
shell=True,
cwd=WORKDIR,
capture_output=True,
text=True,
timeout=60
command, shell=True, cwd=WORKDIR, capture_output=True, text=True, timeout=60
)
output = (result.stdout + result.stderr).strip()
return output[:50000] if output else "(no output)"
Expand All @@ -180,7 +167,7 @@ def run_bash(command: str) -> str:
return f"Error: {e}"


def run_read_file(path: str, limit: int = None) -> str:
def run_read_file(path: str, limit: int | None = None) -> str:
"""
Read file contents with optional line limit.

Expand All @@ -193,9 +180,10 @@ def run_read_file(path: str, limit: int = None) -> str:
text = safe_path(path).read_text()
lines = text.splitlines()

if limit and limit < len(lines):
lines = lines[:limit]
lines.append(f"... ({len(text.splitlines()) - limit} more lines)")
if limit is not None:
limit = max(0, int(limit))
if limit < len(lines):
lines = lines[:limit] + [f"... ({len(lines) - limit} more lines)"]

return "\n".join(lines)[:50000]

Expand All @@ -215,7 +203,7 @@ def run_write_file(path: str, content: str) -> str:
try:
fp = safe_path(path)
fp.parent.mkdir(parents=True, exist_ok=True)
fp.write_text(content)
_ = fp.write_text(content)
return f"Wrote {len(content)} bytes to {path}"

except Exception as e:
Expand All @@ -239,7 +227,7 @@ def run_edit_file(path: str, old_text: str, new_text: str) -> str:
return f"Error: Text not found in {path}"

new_content = content.replace(old_text, new_text, 1)
fp.write_text(new_content)
_ = fp.write_text(new_content)
return f"Edited {path}"

except Exception as e:
Expand All @@ -250,7 +238,8 @@ def run_edit_file(path: str, old_text: str, new_text: str) -> str:
# DISPATCHER PATTERN
# =============================================================================

def execute_tool(name: str, args: dict) -> str:

def execute_tool(name: str, args: dict[str, object]) -> str:
"""
Dispatch tool call to implementation.

Expand All @@ -260,12 +249,21 @@ def execute_tool(name: str, args: dict) -> str:
3. Add case to this dispatcher
"""
if name == "bash":
return run_bash(args["command"])
return run_bash(str(args["command"]))
if name == "read_file":
return run_read_file(args["path"], args.get("limit"))
raw_limit = args.get("limit")
if raw_limit is None:
limit = None
elif isinstance(raw_limit, (int, str)):
limit = int(raw_limit)
else:
return "Error: limit must be an integer"
return run_read_file(str(args["path"]), limit)
if name == "write_file":
return run_write_file(args["path"], args["content"])
return run_write_file(str(args["path"]), str(args["content"]))
if name == "edit_file":
return run_edit_file(args["path"], args["old_text"], args["new_text"])
return run_edit_file(
str(args["path"]), str(args["old_text"]), str(args["new_text"])
)
# Add more tools here...
return f"Unknown tool: {name}"
34 changes: 24 additions & 10 deletions skills/agent-builder/scripts/init_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def run(prompt, history=[]):
while (q := input(">> ").strip()) not in ("q", "quit", ""):
print(run(q, h), "\\n")
''',

1: '''#!/usr/bin/env python3
"""
Level 1 Agent - Model as Agent (~200 lines)
Expand Down Expand Up @@ -112,7 +111,7 @@ def run(prompt, history=[]):
{{"name": "bash", "description": "Run shell command",
"input_schema": {{"type": "object", "properties": {{"command": {{"type": "string"}}}}, "required": ["command"]}}}},
{{"name": "read_file", "description": "Read file contents",
"input_schema": {{"type": "object", "properties": {{"path": {{"type": "string"}}}}, "required": ["path"]}}}},
"input_schema": {{"type": "object", "properties": {{"path": {{"type": "string"}}, "limit": {{"type": "integer"}}}}, "required": ["path"]}}}},
{{"name": "write_file", "description": "Write content to file",
"input_schema": {{"type": "object", "properties": {{"path": {{"type": "string"}}, "content": {{"type": "string"}}}}, "required": ["path", "content"]}}}},
{{"name": "edit_file", "description": "Replace exact text in file",
Expand Down Expand Up @@ -142,7 +141,13 @@ def execute(name: str, args: dict) -> str:

if name == "read_file":
try:
return safe_path(args["path"]).read_text()[:50000]
lines = safe_path(args["path"]).read_text().splitlines()
limit = args.get("limit")
if limit is not None:
limit = max(0, int(limit))
if limit < len(lines):
lines = lines[:limit] + [f"... ({{len(lines) - limit}} more lines)"]
return "\n".join(lines)[:50000]
except Exception as e:
return f"Error: {{e}}"

Expand Down Expand Up @@ -207,11 +212,11 @@ def agent(prompt: str, history: list = None) -> str:
''',
}

ENV_TEMPLATE = '''# API Configuration
ENV_TEMPLATE = """# API Configuration
ANTHROPIC_API_KEY=sk-xxx
ANTHROPIC_BASE_URL=https://api.anthropic.com
MODEL_NAME=claude-sonnet-4-20250514
'''
"""


def create_agent(name: str, level: int, output_dir: Path):
Expand Down Expand Up @@ -263,13 +268,22 @@ def main():
2 Todo (~300 lines) - + TodoWrite for structured planning
3 Subagent (~450) - + Task tool for context isolation
4 Skills (~550) - + Skill tool for domain expertise
"""
""",
)
parser.add_argument("name", help="Name of the agent to create")
parser.add_argument("--level", type=int, default=1, choices=[0, 1, 2, 3, 4],
help="Complexity level (default: 1)")
parser.add_argument("--path", type=Path, default=Path.cwd(),
help="Output directory (default: current directory)")
parser.add_argument(
"--level",
type=int,
default=1,
choices=[0, 1, 2, 3, 4],
help="Complexity level (default: 1)",
)
parser.add_argument(
"--path",
type=Path,
default=Path.cwd(),
help="Output directory (default: current directory)",
)

args = parser.parse_args()
create_agent(args.name, args.level, args.path)
Expand Down