Skip to content

Commit bed7a99

Browse files
committed
feat: migrate from openai to google adk multi-agent system
- Replace OpenAI integration with Google ADK multi-agent architecture - Add specialized agents: MathAgent, TextAgent, InfoAgent, and CoordinatorAgent - Implement custom tools for calculations, text processing, and information retrieval - Add real-time status updates showing agent activity and tool usage - Update streaming implementation to work with ADK event system - Add comprehensive documentation including migration guide and status implementation guide BREAKING CHANGE: Requires Google ADK authentication instead of OpenAI API key. Update environment variables to use GOOGLE_APPLICATION_CREDENTIALS or GOOGLE_API_KEY. chore(git): ignore .vscode directory and update assistant status text Updated .gitignore to exclude .vscode settings directory. Also refined the assistant's loading status message from "is working..." to "is thinking..." to better reflect the AI processing state and added clarifying comments about the UI elements being updated.
1 parent efd12d6 commit bed7a99

File tree

12 files changed

+1782
-58
lines changed

12 files changed

+1782
-58
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ logs/
3838
*.db
3939
.pytype/
4040
.idea/
41+
.vscode/

.vscode/.gitignore

Whitespace-only changes.

.vscode/settings.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"files.exclude": {
3+
"**/.git": true,
4+
"**/.svn": true,
5+
"**/.hg": true,
6+
"**/.DS_Store": true,
7+
"**/Thumbs.db": true,
8+
"**/.classpath": true,
9+
"**/.project": true,
10+
"**/.settings": true,
11+
"**/.factorypath": true
12+
},
13+
"hide-files.files": []
14+
}

CLAUDE.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
This is a Slack AI Agent App built with Bolt for Python, implementing a multi-agent system using Google ADK (Agent Development Kit) with Gemini models. The app provides AI-powered assistance through Slack's Assistant interface with streaming responses.
8+
9+
## Development Commands
10+
11+
### Environment Setup
12+
13+
```sh
14+
# Create and activate virtual environment
15+
python3 -m venv .venv
16+
source .venv/bin/activate # Windows: .\.venv\Scripts\Activate
17+
18+
# Install dependencies
19+
pip install -r requirements.txt
20+
```
21+
22+
### Running the App
23+
24+
```sh
25+
# Using Slack CLI (recommended)
26+
slack run
27+
28+
# Or directly with Python
29+
python3 app.py
30+
```
31+
32+
### Code Quality
33+
34+
```sh
35+
# Lint code
36+
ruff check
37+
38+
# Format code
39+
ruff format
40+
```
41+
42+
### Testing
43+
44+
```sh
45+
# Run all tests
46+
pytest
47+
48+
# Run specific test file
49+
pytest tests/test_file.py
50+
51+
# Run with verbose output
52+
pytest -v
53+
```
54+
55+
## Architecture
56+
57+
### Multi-Agent System
58+
59+
The application uses Google ADK to implement a hierarchical multi-agent architecture:
60+
61+
- **CoordinatorAgent** (`ai/agents.py:55-78`): Root agent that analyzes user requests and delegates to specialized agents
62+
- **MathAgent** (`ai/agents.py:20-28`): Handles mathematical calculations and numerical operations
63+
- **TextAgent** (`ai/agents.py:31-40`): Processes text formatting, word counting, and list creation
64+
- **InfoAgent** (`ai/agents.py:43-52`): Provides current time, help information, and general queries
65+
66+
Each agent uses the `gemini-2.0-flash` model and has access to specific tools defined in `ai/tools.py`.
67+
68+
### Request Flow
69+
70+
1. **Entry Point** (`app.py`): Thin entry point that initializes the Bolt app and registers listeners
71+
2. **Listener Registration** (`listeners/__init__.py`): Routes incoming Slack events to appropriate handlers
72+
3. **Event Handlers**:
73+
- `listeners/assistant/message.py`: Handles messages in assistant threads
74+
- `listeners/events/app_mentioned.py`: Handles @mentions of the bot
75+
- `listeners/assistant/assistant_thread_started.py`: Sets up suggested prompts when threads start
76+
4. **LLM Integration** (`ai/llm_caller.py`): Provides `call_llm()` async generator that streams responses from the ADK agent system
77+
5. **Response Streaming**: Uses Slack's `chat_stream` API to stream chunks back to the user in real-time
78+
79+
### Key Design Patterns
80+
81+
- **Async Streaming**: All LLM responses are streamed using async generators to provide real-time feedback
82+
- **Event Loop Management**: Creates new event loops in synchronous Bolt handlers to call async ADK functions
83+
- **Session Management**: Uses thread timestamps as session IDs to maintain conversation context
84+
- **Tool-Based Architecture**: Agents use Python functions as tools, automatically exposed to the LLM by ADK
85+
86+
## Configuration
87+
88+
### Required Environment Variables
89+
90+
```sh
91+
SLACK_BOT_TOKEN=xoxb-... # From OAuth & Permissions
92+
SLACK_APP_TOKEN=xapp-... # App-level token with connections:write
93+
```
94+
95+
### Google ADK Authentication (one of):
96+
97+
```sh
98+
# Option 1: Service account (production)
99+
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json
100+
101+
# Option 2: API key (development)
102+
GOOGLE_API_KEY=your-api-key
103+
104+
# Option 3: Use `gcloud auth application-default login`
105+
```
106+
107+
## Adding New Agents
108+
109+
To add a new specialized agent:
110+
111+
1. Create tools in `ai/tools.py` following the existing pattern (functions returning `Dict[str, Any]`)
112+
2. Define the agent in `ai/agents.py`:
113+
```python
114+
new_agent = Agent(
115+
name="AgentName",
116+
model="gemini-2.0-flash",
117+
description="When to use this agent",
118+
instruction="Detailed instructions for the agent",
119+
tools=[tool1, tool2],
120+
)
121+
```
122+
3. Add the agent to `coordinator_agent.sub_agents` list
123+
4. Update the coordinator's instruction to explain when to delegate to the new agent
124+
125+
## Slack-Specific Conventions
126+
127+
- **Markdown Compatibility**: Agents are instructed to convert markdown to Slack-compatible format
128+
- **Slack Syntax Preservation**: User mentions (`<@USER_ID>`) and channel mentions (`<#CHANNEL_ID>`) must be preserved as-is in responses
129+
- **Status Messages**: Use playful loading messages during "thinking" state (see `listeners/assistant/message.py:40-46`)
130+
- **Feedback Blocks**: Responses include feedback blocks for user interaction (`listeners/views/feedback_block.py`)
131+
132+
## Project Structure Notes
133+
134+
- `/listeners`: Organized by Slack Platform feature (events, assistant, actions, views)
135+
- `/ai`: Contains all LLM and agent-related code, separated from Slack-specific logic
136+
- Socket Mode is used for local development (no public URL required)
137+
- For OAuth/distribution, use `app_oauth.py` instead of `app.py`

ai/agents.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""
2+
Multi-agent system using Google ADK.
3+
4+
This module defines a multi-agent system with specialized agents for different tasks.
5+
"""
6+
7+
from google.adk.agents import Agent
8+
from google.adk.models.lite_llm import LiteLlm
9+
10+
from .tools import (
11+
get_current_time,
12+
calculate,
13+
format_text,
14+
count_words,
15+
create_list,
16+
get_help_info,
17+
)
18+
19+
# Configure OpenAI model via LiteLLM
20+
# Requires OPENAI_API_KEY environment variable
21+
openai_model = LiteLlm(model="openai/gpt-4o")
22+
23+
24+
# Specialized agent for mathematical operations
25+
math_agent = Agent(
26+
name="MathAgent",
27+
model=openai_model,
28+
description="Specializes in mathematical calculations and numerical operations. Use this agent for any math-related queries.",
29+
instruction="""You are a mathematical expert. You can perform calculations, solve equations,
30+
and help with numerical problems. Use the calculate tool to evaluate mathematical expressions.
31+
Always explain your calculations clearly.""",
32+
tools=[calculate],
33+
)
34+
35+
# Specialized agent for text processing
36+
text_agent = Agent(
37+
name="TextAgent",
38+
model=openai_model,
39+
description="Specializes in text processing, formatting, and analysis. Use this agent for text manipulation tasks.",
40+
instruction="""You are a text processing expert. You can format text, count words,
41+
create lists, and analyze text content. Use the available tools to help users with text-related tasks.
42+
When you include markdown text, convert them to Slack compatible ones.
43+
When a prompt has Slack's special syntax like <@USER_ID> or <#CHANNEL_ID>, you must keep them as-is in your response.""",
44+
tools=[format_text, count_words, create_list],
45+
)
46+
47+
# Specialized agent for information and utilities
48+
info_agent = Agent(
49+
name="InfoAgent",
50+
model=openai_model,
51+
description="Provides general information, current time, and help about available capabilities.",
52+
instruction="""You are an information assistant. You can provide the current time,
53+
help users understand what tools are available, and answer general questions.
54+
When you include markdown text, convert them to Slack compatible ones.
55+
When a prompt has Slack's special syntax like <@USER_ID> or <#CHANNEL_ID>, you must keep them as-is in your response.""",
56+
tools=[get_current_time, get_help_info],
57+
)
58+
59+
# Coordinator agent that routes requests to specialized agents
60+
coordinator_agent = Agent(
61+
name="CoordinatorAgent",
62+
model=openai_model,
63+
description="Main coordinator that routes user requests to specialized agents.",
64+
instruction="""You are a helpful assistant coordinator in a Slack workspace.
65+
Users in the workspace will ask you to help them with various tasks.
66+
67+
You have access to specialized agents:
68+
- MathAgent: For mathematical calculations and numerical operations
69+
- TextAgent: For text processing, formatting, and analysis
70+
- InfoAgent: For general information, current time, and help
71+
72+
Analyze the user's request and delegate to the appropriate specialized agent:
73+
- For math problems, calculations, or numerical queries -> use MathAgent
74+
- For text formatting, word counting, or list creation -> use TextAgent
75+
- For time queries, help requests, or general information -> use InfoAgent
76+
- For general conversation or questions that don't fit the above -> answer directly
77+
78+
When you include markdown text, convert them to Slack compatible ones.
79+
When a prompt has Slack's special syntax like <@USER_ID> or <#CHANNEL_ID>, you must keep them as-is in your response.
80+
81+
Always be professional, helpful, and friendly in your responses.""",
82+
sub_agents=[math_agent, text_agent, info_agent],
83+
)
84+
85+
86+
def get_root_agent() -> Agent:
87+
"""
88+
Get the root coordinator agent for the multi-agent system.
89+
90+
Returns:
91+
Agent: The coordinator agent that routes requests to specialized agents.
92+
"""
93+
return coordinator_agent

0 commit comments

Comments
 (0)