INTEGRATION_EXAMPLE.md
1 # How to Integrate Multi-Agent Router 2 3 ## Quick Integration Guide 4 5 Here's exactly how to add the AgentRouter to `kamaji chat`: 6 7 ### Option 1: Simple Integration (Recommended) 8 9 ```python 10 # In kamaji/commands/chat.py 11 12 from kamaji.agents.router import AgentRouter 13 14 def run_chat(temperature: float = None, files: Optional[List[str]] = None): 15 # ... existing setup code ... 16 17 llm = get_llm(temperature=temperature) 18 19 # Replace agent_executor with router 20 router = AgentRouter(llm, verbose=False) 21 22 # Show available agents in welcome 23 print("\nš„ Multi-Agent Mode ENABLED") 24 print("\nType '@help' to see available specialized agents\n") 25 26 while True: 27 user_input = input("You: ").strip() 28 29 # Handle special commands 30 if user_input == "@help": 31 print(router.help()) 32 continue 33 34 if user_input.lower() in ['exit', 'quit']: 35 break 36 37 # Route to appropriate agent 38 print("\nKamaji: ", end="", flush=True) 39 40 try: 41 # Show which agent is being used 42 agent_name, task = router.parse_input(user_input) 43 if agent_name != "general": 44 print(f"[using @{agent_name}] ", end="", flush=True) 45 46 # Execute with routing 47 result = router.invoke(user_input) 48 response = result.get('output', str(result)) 49 50 print(response) 51 52 except Exception as e: 53 print(f"\nā Error: {e}") 54 # Check if React format error 55 if "Invalid Format" in str(e): 56 print("š” TIP: Try using a larger LLM model for better agent support") 57 ``` 58 59 ### Option 2: Hybrid Mode (Both Single Agent and Router) 60 61 ```python 62 # Let users choose 63 def run_chat(temperature: float = None, files: Optional[List[str]] = None, multi_agent: bool = True): 64 65 if multi_agent: 66 # Use router 67 router = AgentRouter(llm) 68 agent_or_router = router 69 else: 70 # Use single agent (original behavior) 71 agent_or_router = create_agent_executor(llm) 72 73 # Then invoke with: 74 result = agent_or_router.invoke(user_input) 75 ``` 76 77 Add CLI flag: 78 ```python 79 # In cli.py 80 chat_parser.add_argument( 81 '--multi-agent', 82 action='store_true', 83 help='Enable multi-agent mode with specialized agents' 84 ) 85 ``` 86 87 ### TUI Integration 88 89 ```python 90 # In kamaji/commands/tui.py 91 92 from kamaji.agents.router import AgentRouter 93 94 class KamajiTUI(App): 95 96 def on_mount(self): 97 # ... existing setup ... 98 99 # Option A: Always use router 100 self.agent_router = AgentRouter(self.llm, verbose=False) 101 102 # Update welcome message 103 welcome_msg += "\n" + self.agent_router.help() 104 105 @work(exclusive=True, thread=True) 106 def generate_response(self, user_input: str) -> None: 107 messages = self.query_one("#messages", MessageDisplay) 108 109 # Handle @help 110 if user_input.strip() == "@help": 111 help_text = self.agent_router.help() 112 self.call_from_thread( 113 messages.write, 114 Panel(help_text, title="š„ Available Agents") 115 ) 116 return 117 118 # Show which agent will be used 119 agent_name, task = self.agent_router.parse_input(user_input) 120 if agent_name != "general": 121 self.call_from_thread( 122 messages.write, 123 f"[dim]Using @{agent_name} agent...[/dim]" 124 ) 125 126 # Execute with routing 127 try: 128 result = self.agent_router.invoke(user_input) 129 response = result.get('output', str(result)) 130 131 self.call_from_thread( 132 messages.write, 133 Panel(response, title=f"š„ Kamaji (@{agent_name})") 134 ) 135 except Exception as e: 136 # Error handling... 137 ``` 138 139 --- 140 141 ## Testing the Integration 142 143 ### Test 1: Explicit Agent Selection 144 145 ```bash 146 kamaji chat 147 ``` 148 149 ``` 150 You: @review Check kamaji/tools.py 151 152 [using @review] š Analyzing kamaji/tools.py... 153 154 š Code Review Results: 155 156 ā Syntax: No errors found 157 ā Code Quality: Good separation of concerns 158 ā ļø Missing error handling in execute_shell_command (line 21) 159 š” Suggestion: Add timeout parameter validation 160 161 Overall: 8/10 162 ``` 163 164 ### Test 2: Auto-Routing 165 166 ``` 167 You: Review the authentication code 168 169 [using @review] š Auto-detected code review request... 170 171 [proceeds with review] 172 ``` 173 174 ### Test 3: Documentation Agent 175 176 ``` 177 You: @docs Write a README for the agents module 178 179 [using @docs] š Creating documentation... 180 181 ā Created README.md with: 182 - Overview of multi-agent system 183 - Usage examples 184 - Available agents list 185 ``` 186 187 ### Test 4: General Agent (Default) 188 189 ``` 190 You: What files are in this directory? 191 192 [using general] š Listing directory contents... 193 194 Files: 195 - kamaji/ 196 - setup.py 197 - README.md 198 [etc] 199 ``` 200 201 --- 202 203 ## Adding Your Own Agent 204 205 ### Step 1: Create Agent File 206 207 ```python 208 # kamaji/agents/refactoring.py 209 210 from langchain.agents import Tool, AgentExecutor, create_react_agent 211 from kamaji.tools import read_file, write_file_smart 212 213 def suggest_refactoring(file_path: str) -> str: 214 """Analyze code and suggest refactoring opportunities.""" 215 # Implementation 216 return suggestions 217 218 def create_refactoring_agent(llm): 219 tools = [ 220 Tool(name="read_file", func=read_file, ...), 221 Tool(name="write_file", func=write_file_smart, ...), 222 Tool(name="suggest_refactoring", func=suggest_refactoring, ...), 223 ] 224 225 prompt = PromptTemplate.from_template(""" 226 You are a refactoring expert. 227 228 Your job: 229 - Identify code smells 230 - Suggest design pattern improvements 231 - Simplify complex code 232 233 Tools: {tools} 234 Question: {input} 235 Thought: {agent_scratchpad} 236 """) 237 238 agent = create_react_agent(llm, tools, prompt) 239 return AgentExecutor(agent=agent, tools=tools, ...) 240 ``` 241 242 ### Step 2: Register in Router 243 244 ```python 245 # kamaji/agents/router.py 246 247 from kamaji.agents.refactoring import create_refactoring_agent 248 249 class AgentRouter: 250 def __init__(self, llm): 251 self._agents = { 252 "general": None, 253 "review": None, 254 "docs": None, 255 "refactor": None, # Add here 256 } 257 258 self._keywords = { 259 "review": [...], 260 "docs": [...], 261 "refactor": ["refactor", "simplify", "clean up", "improve code"], 262 } 263 264 def _get_agent(self, agent_name: str): 265 # ... 266 elif agent_name == "refactor": 267 agent = create_refactoring_agent(self.llm) 268 # ... 269 270 def list_agents(self): 271 return { 272 # ... existing ... 273 "@refactor": "Refactoring specialist - improves code structure", 274 } 275 ``` 276 277 ### Step 3: Use It 278 279 ``` 280 You: @refactor Simplify the database queries in models.py 281 282 [using @refactor] š§ Analyzing code structure... 283 284 ā Suggested refactorings: 285 1. Extract repeated DB connection logic into context manager 286 2. Replace nested loops with list comprehensions 287 3. Use dataclasses instead of manual __init__ 288 289 Applied 3 refactorings to models.py 290 ``` 291 292 --- 293 294 ## Current Status 295 296 **What Works**: 297 ā Router parses @agent_name syntax 298 ā Auto-routing based on keywords 299 ā Multiple specialized agents with different tools 300 ā Lazy agent loading 301 ā Help command 302 303 **What Doesn't Work Yet**: 304 ā React format errors with smaller models 305 ā Router not integrated into chat.py yet 306 ā Router not integrated into tui.py yet 307 308 **Next Steps**: 309 1. Integrate router into chat.py (5 min) 310 2. Integrate router into tui.py (10 min) 311 3. Test with different LLM models 312 4. Consider alternative to React format (function calling) 313 314 --- 315 316 ## Alternative: Function Calling (Future) 317 318 If React format continues to fail, implement function calling: 319 320 ```python 321 # Future: kamaji/agent_function_calling.py 322 323 def simple_agent_executor(llm, tools, task): 324 """Simpler agent that doesn't require React format.""" 325 326 # Step 1: LLM picks tool 327 tool_prompt = f""" 328 Task: {task} 329 Available tools: {[t.name for t in tools]} 330 331 Which tool should be used first? Reply with ONLY the tool name. 332 """ 333 tool_name = llm.predict(tool_prompt).strip() 334 335 # Step 2: LLM provides input 336 input_prompt = f""" 337 Task: {task} 338 Tool: {tool_name} 339 340 What input should be passed to this tool? 341 """ 342 tool_input = llm.predict(input_prompt).strip() 343 344 # Step 3: Execute tool 345 tool = next(t for t in tools if t.name == tool_name) 346 result = tool.func(tool_input) 347 348 # Step 4: LLM formats answer 349 answer_prompt = f""" 350 Task: {task} 351 Tool used: {tool_name} 352 Result: {result} 353 354 Provide a final answer to the user. 355 """ 356 answer = llm.predict(answer_prompt) 357 358 return answer 359 ``` 360 361 This avoids the strict React format but still uses tools effectively.