π If you find this project useful, please consider giving it a star! It helps the project grow.
AI agent orchestration framework built on the Google Agent Development Kit (ADK), exposed through a FastAPI REST interface. CabaModel decouples agent definition, execution, and infrastructure behind a hexagonal (ports & adapters) architecture, delivering a resilient, schema-validated layer for running Gemini-native agents with tool-calling loops.
Live Demo: cabamodel.onrender.com/ui β minimal chat interface, talk to the agents directly. Raw API docs (Swagger) at /docs.
Clone and run the agents locally:
git clone https://github.com/gabaoun/CabaModel.git
cd CabaModel
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
# Run the FastAPI server
uvicorn main:app --reloadThe API and Swagger docs will be available at http://localhost:8000/docs.
- ADK Runner Execution: Built on the
Runnerpattern withInMemorySessionService, handling agentic loops, event streams, and native tool calling end-to-end. - Hexagonal Architecture: Strict separation between Domain (
AgentConfigschemas), Application (agent definitions), and Infrastructure (ADK adapters, HTTP layer). - Schema-Validated Configuration: Agent definitions are Pydantic v2 models with enforced constraints β name length, model selection, description, instruction, and tool registration.
- Asynchronous & Non-Blocking: Full
asynciopipeline; synchronous tools are bridged viaasyncio.to_threadto keep the event loop unblocked. - Resilience: Standardized retry policy (3 attempts, exponential backoff 4β10s) around external model calls.
- Type-Safe Tooling: Strict mypy compliance and ruff enforcement with a 100-column line length.
- Pluggable Agent Registry: New agents are registered by defining an
AgentConfigin the application layer β no infrastructure changes required.
- Hexagonal Architecture (Ports & Adapters): Domain schemas, agent definitions, and ADK infrastructure are strictly layered so the ADK SDK β or the LLM provider behind it β can be swapped without touching agent logic or the HTTP layer.
- Pydantic v2 for Agent Configuration:
AgentConfigis schema-validated at definition time, not at request time. Malformed agent definitions fail at import/startup, never mid-request. asyncio.to_threadfor Sync Tool Bridging: ADK tool functions are plain sync callables; bridging them through a thread pool keeps the single event loop unblocked instead of forcing every tool to be rewritten async.- Retry at the Model-Call Boundary, Not the Request Boundary:
tenacity-backed exponential backoff wraps only the external Gemini call, so a 429/RESOURCE_EXHAUSTEDis retried without re-running already-completed tool calls in the same turn. - Pluggable Agent Registry over a Central Dispatcher: New agents register themselves as
AgentConfiginstances in the application layer β no changes toinfrastructure/api.pyor the ADK adapter are needed to add one.
| Layer | Technology |
|---|---|
| Runtime | Python >= 3.14 |
| Agent Framework | google-adk (>= 1.23.0) |
| LLM | Gemini (google-generativeai >= 0.8.6) |
| API Framework | FastAPI + uvicorn |
| Validation | Pydantic v2 + pydantic-settings |
| Resilience | tenacity (exponential backoff) |
| Config | python-dotenv |
| Tooling | mypy (strict), ruff |
graph TD
A["HTTP Layer<br/>infrastructure/api.py<br/>FastAPI POST /chat"] --> B
B["Infrastructure Adapters<br/>agent_service.py<br/>AgentFactory, async_tool, run_agent_async, standard_retry"] -->|instantiates| C
C["Application Agents<br/>temporal_agent.py (time/date tools)<br/>c4b4_bot.py (community support)"] -->|defined by| D
D["Domain Schemas<br/>models.py β AgentConfig (Pydantic v2)"]
flowchart TD
A["POST /chat { message, agent_type }"] --> B{"validate agent_type"}
B --> C["select agent: temporal | c4b4"]
C --> D["run_agent_async(agent, message)"]
D --> E["ADK Runner (auto_create_session)"]
E --> F["agentic loop: model β tools<br/>(Gemini function calling)"]
F --> G["sync tools bridged via asyncio.to_thread"]
G --> H["collect text events from stream"]
H --> I{"429 / RESOURCE_EXHAUSTED?"}
I -->|yes| J["retry, exponential backoff"]
J --> E
I -->|no| K["{ response, agent_name }"]
CabaModel/
βββ main.py # Entry point (env check + uvicorn)
βββ src/cabamodel/
β βββ domain/
β β βββ models.py # AgentConfig Pydantic schema
β βββ application/
β β βββ temporal_agent.py # Time/date agent (tool-enabled)
β β βββ c4b4_bot.py # Community support agent
β βββ infrastructure/
β βββ agent_service.py # AgentFactory, Runner, retry policy
β βββ api.py # FastAPI application
βββ .env.example
βββ pyproject.toml
- Python >= 3.14
- A Google API key with access to the Gemini models
git clone <REPOSITORY_URL>
cd CabaModel
python -m venv venv
# Windows
venv\Scripts\activate
# Linux/macOS
source venv/bin/activate
pip install -e .Create your environment file and add your API key:
cp .env.example .env
# Set GOOGLE_API_KEY=<your_key>Start the API:
python main.pyInteractive OpenAPI documentation is available at http://127.0.0.1:8000/docs.
The orchestration service can be used directly from Python code:
from src.cabamodel.application.temporal_agent import root_agent
from src.cabamodel.infrastructure.agent_service import run_agent_async
async def main():
response = await run_agent_async(root_agent, "What time is it now?")
print(f"Agent Response: {response}")The run_agent_async contract handles the tool-calling loop and event stream automatically.
| Variable | Default | Description |
|---|---|---|
GOOGLE_API_KEY |
(required) | API key for Gemini model access. The server refuses to start without it. |
ADK_LOG_LEVEL |
INFO |
Logging verbosity for the ADK runtime. |
Routes a user message to a registered agent and returns its generated response.
Request body:
{
"message": "What time is it now?",
"agent_type": "temporal"
}| Field | Type | Required | Description |
|---|---|---|---|
message |
string | yes | User prompt to dispatch to the agent. |
agent_type |
string | no | Agent selector: "temporal" or "c4b4". Defaults to "temporal". |
Response body:
{
"response": "It is currently 14:32:05.",
"agent_name": "Temporal_Tool_Agent"
}Error responses: 400 for an invalid agent_type; 500 for execution failures.
Health probe returning service status and documentation link.
| Agent | Model | Tools | Use Case |
|---|---|---|---|
Temporal_Tool_Agent |
gemini-flash-latest |
get_current_time, get_current_weekday |
Real-time system clock queries |
C4B4_Assistant |
gemini-flash-latest |
β | Automated community support for the C4B4 ecosystem |
Distributed under the Apache 2.0 License. See LICENSE for details.
