minimal-agent.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #!/usr/bin/env python3
  2. """
  3. Minimal Agent Template - Copy and customize this.
  4. This is the simplest possible working agent (~80 lines).
  5. It has everything you need: 3 tools + loop.
  6. Usage:
  7. 1. Set ANTHROPIC_API_KEY environment variable
  8. 2. python minimal-agent.py
  9. 3. Type commands, 'q' to quit
  10. """
  11. from anthropic import Anthropic
  12. from pathlib import Path
  13. import subprocess
  14. import os
  15. # Configuration
  16. client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
  17. MODEL = os.getenv("MODEL_NAME", "claude-sonnet-4-20250514")
  18. WORKDIR = Path.cwd()
  19. # System prompt - keep it simple
  20. SYSTEM = f"""You are a coding agent at {WORKDIR}.
  21. Rules:
  22. - Use tools to complete tasks
  23. - Prefer action over explanation
  24. - Summarize what you did when done"""
  25. # Minimal tool set - add more as needed
  26. TOOLS = [
  27. {
  28. "name": "bash",
  29. "description": "Run shell command",
  30. "input_schema": {
  31. "type": "object",
  32. "properties": {"command": {"type": "string"}},
  33. "required": ["command"]
  34. }
  35. },
  36. {
  37. "name": "read_file",
  38. "description": "Read file contents",
  39. "input_schema": {
  40. "type": "object",
  41. "properties": {"path": {"type": "string"}},
  42. "required": ["path"]
  43. }
  44. },
  45. {
  46. "name": "write_file",
  47. "description": "Write content to file",
  48. "input_schema": {
  49. "type": "object",
  50. "properties": {
  51. "path": {"type": "string"},
  52. "content": {"type": "string"}
  53. },
  54. "required": ["path", "content"]
  55. }
  56. },
  57. ]
  58. def execute_tool(name: str, args: dict) -> str:
  59. """Execute a tool and return result."""
  60. if name == "bash":
  61. try:
  62. r = subprocess.run(
  63. args["command"], shell=True, cwd=WORKDIR,
  64. capture_output=True, text=True, timeout=60
  65. )
  66. return (r.stdout + r.stderr).strip() or "(empty)"
  67. except subprocess.TimeoutExpired:
  68. return "Error: Timeout"
  69. if name == "read_file":
  70. try:
  71. return (WORKDIR / args["path"]).read_text()[:50000]
  72. except Exception as e:
  73. return f"Error: {e}"
  74. if name == "write_file":
  75. try:
  76. p = WORKDIR / args["path"]
  77. p.parent.mkdir(parents=True, exist_ok=True)
  78. p.write_text(args["content"])
  79. return f"Wrote {len(args['content'])} bytes to {args['path']}"
  80. except Exception as e:
  81. return f"Error: {e}"
  82. return f"Unknown tool: {name}"
  83. def agent(prompt: str, history: list = None) -> str:
  84. """Run the agent loop."""
  85. if history is None:
  86. history = []
  87. history.append({"role": "user", "content": prompt})
  88. while True:
  89. response = client.messages.create(
  90. model=MODEL,
  91. system=SYSTEM,
  92. messages=history,
  93. tools=TOOLS,
  94. max_tokens=8000,
  95. )
  96. # Build assistant message
  97. history.append({"role": "assistant", "content": response.content})
  98. # If no tool calls, return text
  99. if response.stop_reason != "tool_use":
  100. return "".join(b.text for b in response.content if hasattr(b, "text"))
  101. # Execute tools
  102. results = []
  103. for block in response.content:
  104. if block.type == "tool_use":
  105. print(f"> {block.name}: {block.input}")
  106. output = execute_tool(block.name, block.input)
  107. print(f" {output[:100]}...")
  108. results.append({
  109. "type": "tool_result",
  110. "tool_use_id": block.id,
  111. "content": output
  112. })
  113. history.append({"role": "user", "content": results})
  114. if __name__ == "__main__":
  115. print(f"Minimal Agent - {WORKDIR}")
  116. print("Type 'q' to quit.\n")
  117. history = []
  118. while True:
  119. try:
  120. query = input(">> ").strip()
  121. except (EOFError, KeyboardInterrupt):
  122. break
  123. if query in ("q", "quit", "exit", ""):
  124. break
  125. print(agent(query, history))
  126. print()