/ docs / integration / INTEGRATION_EXAMPLE.md
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.