Skip to content

Commit 390361e

Browse files
kovtcharov-amdOvtcharovkovtcharov
authored
refactor(agents): migrate chat to hub (#1102) (#1456)
## Why this matters ChatAgent — the flagship conversational agent powering `gaia chat` (and `gaia chat --ui`) under its `chat`, `doc`, and `file` profiles — was the last family of registry *builtins* still hardcoded inside the core framework wheel. It now ships as the standalone **`gaia-agent-chat`** wheel under `hub/agents/python/chat/`, with `chat`/`doc`/`file` registered as three `gaia.agent` entry points that the registry discovers automatically. The core wheel no longer hardcodes them, so the chat family versions independently like every other migrated agent. `gaia chat` resolves the agent through the registry and **fails loudly with an install hint** if the wheel is absent (mirroring how #1446 made `gaia browse`/`gaia analyze` resolve). All three profiles, their full+lite model tiers (via `registry.build_model_tiers`), and their per-profile prompt/tool wiring are preserved exactly. Continues the #1102 Agent Hub restructure after connectors-demo (#1442) and analyst/browser (#1446). The shared `FileToolsMixin` (directory monitoring) stays framework-side — promoted to `gaia.agents.tools.file_monitor_tools` — since tool mixins are framework code (#1396). ## Test plan - [x] `python util/lint.py --all` — black/isort clean (the only pylint hit, `os.geteuid` in `lemonade_installer.py`, is a pre-existing Windows-only false positive; mypy is warning-only) - [x] `pytest tests/unit/agents/test_registry.py tests/unit/test_agents_split.py tests/unit/cli/test_cli_smoke.py` — registry + split green; the 4 `cli_smoke` `gaia-code`/`gaia-emr` console-script hits are pre-existing shared-env pollution (verified passing on the base checkout), unrelated to chat - [x] `pip install -e hub/agents/python/chat && pytest hub/agents/python/chat/tests/` — 7 passed (registration shapes for chat/doc/file, lazy re-exports, discovery, `installed:` namespacing) - [x] `pytest` across the chat-touched framework suites (chat agent, integration, system-prompt budget, browser tools, multi-device, required-connectors, registry factory, chat-UI helpers) — 182 passed with the wheel installed; all skip cleanly via `importorskip` in a framework-only env - [x] Registry discovery lists `chat`/`doc`/`file` as `source=installed` with `installed:chat` namespace; `builder`/`email` remain the only resident builtins - [ ] CI: the `Chat Agent Tests` workflow installs the wheel and runs both the package smoke tests and the framework session/RAG/path-validation suites --------- Co-authored-by: Ovtcharov <kovtchar@amd.com> Co-authored-by: Kalin Ovtcharov <kalin@extropolis.ai>
1 parent 21fff02 commit 390361e

83 files changed

Lines changed: 786 additions & 1111 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test_chat_agent.yml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
22
# SPDX-License-Identifier: MIT
33

4-
# This workflow tests the GAIA Chat Agent functionality
5-
# Tests include: Session persistence, chat history, RAG, and path validation
4+
# This workflow tests the GAIA Chat Agent, which ships as the standalone
5+
# gaia-agent-chat wheel (#1102). Tests include the wheel's own smoke tests
6+
# plus the framework-side session, RAG, and path-validation suites.
67

78
name: Chat Agent Tests
89

@@ -11,8 +12,9 @@ on:
1112
push:
1213
branches: [ main ]
1314
paths:
14-
- 'src/gaia/agents/chat/**'
15+
- 'hub/agents/python/chat/**'
1516
- 'src/gaia/agents/base/**'
17+
- 'src/gaia/agents/tools/**'
1618
- 'src/gaia/rag/**'
1719
- 'src/gaia/chat/**'
1820
- 'tests/test_chat_agent.py'
@@ -23,8 +25,9 @@ on:
2325
branches: [ main ]
2426
types: [opened, synchronize, reopened, ready_for_review]
2527
paths:
26-
- 'src/gaia/agents/chat/**'
28+
- 'hub/agents/python/chat/**'
2729
- 'src/gaia/agents/base/**'
30+
- 'src/gaia/agents/tools/**'
2831
- 'src/gaia/rag/**'
2932
- 'src/gaia/chat/**'
3033
- 'tests/test_chat_agent.py'
@@ -67,6 +70,19 @@ jobs:
6770
uv pip install --system -e .[dev,rag]
6871
# Install pytest-mock for mocking tests
6972
uv pip install --system pytest-mock
73+
# ChatAgent ships as the standalone gaia-agent-chat wheel (#1102)
74+
uv pip install --system -e hub/agents/python/chat
75+
76+
- name: Run Chat Agent Package Tests
77+
env:
78+
GAIA_MEMORY_DISABLED: "1"
79+
run: |
80+
echo "================================================================"
81+
echo " CHAT AGENT PACKAGE TESTS"
82+
echo "================================================================"
83+
echo "Testing registration shapes, lazy re-exports, and discovery..."
84+
echo ""
85+
python -m pytest hub/agents/python/chat/tests/ -v --tb=short
7086
7187
- name: Run Chat Agent Unit Tests
7288
env:

.github/workflows/test_security.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ jobs:
5858
run: curl -LsSf https://astral.sh/uv/install.sh | sh
5959

6060
- name: Install dependencies
61-
run: uv pip install --system -e .[dev,rag]
61+
run: |
62+
uv pip install --system -e .[dev,rag]
63+
# verify_*.py instantiate ChatAgent, which ships as the standalone
64+
# gaia-agent-chat wheel (#1102).
65+
uv pip install --system -e hub/agents/python/chat
6266
6367
- name: Run Path Validator Security Tests
6468
env:
@@ -155,7 +159,12 @@ jobs:
155159
shell: pwsh
156160

157161
- name: Install dependencies
158-
run: uv pip install --system -e .[dev,rag]
162+
run: |
163+
uv pip install --system -e .[dev,rag]
164+
# verify_*.py instantiate ChatAgent, which ships as the standalone
165+
# gaia-agent-chat wheel (#1102).
166+
uv pip install --system -e hub/agents/python/chat
167+
shell: pwsh
159168

160169
- name: Run Path Validator Security Tests
161170
shell: pwsh

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"name": "Chat Agent Debug - Model Selection",
5454
"type": "debugpy",
5555
"request": "launch",
56-
"module": "gaia.agents.chat.app",
56+
"module": "gaia_agent_chat.app",
5757
"args": ["--query", "hi"],
5858
"cwd": "${workspaceFolder}",
5959
"env": {

docs/guides/chat.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ gaia chat --index document.pdf --debug
208208

209209
```python Python Debug
210210
# Python SDK with debug — ChatAgent takes a single ChatAgentConfig
211-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
211+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
212212

213213
config = ChatAgentConfig(
214214
rag_documents=['document.pdf'],
@@ -322,7 +322,7 @@ is set, the UI toggle reflects the effective value and disables itself — which
322322
handy for the eval harness:
323323

324324
```python
325-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
325+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
326326

327327
agent = ChatAgent(ChatAgentConfig(prompt_profile="doc", dynamic_tools=True))
328328
```

docs/plans/agent-ui-eval-benchmark.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ Single-scenario run: ~$0.10-0.15.
10591059
"root_cause": "Smart Discovery workflow uses query keywords as file search patterns. Needs to extract likely document names, not just topic keywords.",
10601060
"recommended_fix": {
10611061
"target": "system_prompt",
1062-
"file": "src/gaia/agents/chat/agent.py",
1062+
"file": "hub/agents/python/chat/gaia_agent_chat/agent.py",
10631063
"description": "In Smart Discovery section, instruct agent to search for common document names related to the topic, not just the exact query terms."
10641064
}
10651065
}

docs/plans/email-triage-agent.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ v0.20.0 for GaiaAgent broadly. The email-agent path explicitly opts out:
567567
flips red loudly if an email-content payload is ever seen heading to a cloud
568568
backend. This is the alarm, not the defense — the defense is the tag check.
569569
- An integration test asserts this invariant on every PR touching `gaia/llm/`
570-
or `gaia/agents/chat/`.
570+
or `hub/agents/python/chat/`.
571571

572572
Nothing in this spec relies on the user "just trusting" the local-only claim.
573573

docs/plans/security-model.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,8 @@ The following security measures are already implemented in the codebase:
783783

784784
| Measure | Location | Description |
785785
|---------|----------|-------------|
786-
| Shell command whitelist | `src/gaia/agents/chat/tools/shell_tools.py` | `ALLOWED_COMMANDS` set restricts CLI tool to read-only commands |
787-
| Git command whitelist | `src/gaia/agents/chat/tools/shell_tools.py` | Only read-only git subcommands (`status`, `log`, `diff`, etc.) |
786+
| Shell command whitelist | `src/gaia/agents/tools/shell_tools.py` | `ALLOWED_COMMANDS` set restricts CLI tool to read-only commands |
787+
| Git command whitelist | `src/gaia/agents/tools/shell_tools.py` | Only read-only git subcommands (`status`, `log`, `diff`, etc.) |
788788
| Localhost-only MCP bridge | `src/gaia/mcp/mcp.json` | `GAIA_MCP_HOST` defaults to `localhost` |
789789
| Subprocess timeout | `src/gaia/mcp/external_services.py` | `timeout=30` on MCP subprocess calls |
790790
| Tool registry validation | `src/gaia/agents/base/agent.py` | Rejects unregistered tool names |

docs/plans/tool-loader.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "Dynamic Tool Loader"
33
---
44

55
<Info>
6-
**Source Code:** [`src/gaia/agents/base/tool_loader.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/base/tool_loader.py) · bundles [`src/gaia/agents/chat/tool_bundles.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/chat/tool_bundles.py)
6+
**Source Code:** [`src/gaia/agents/base/tool_loader.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/base/tool_loader.py) · bundles [`hub/agents/python/chat/gaia_agent_chat/tool_bundles.py`](https://github.com/amd/gaia/blob/main/hub/agents/python/chat/gaia_agent_chat/tool_bundles.py)
77
</Info>
88

99
<Note>
@@ -272,7 +272,7 @@ when set — the toggle then reflects the effective value and disables — so τ
272272
the cap stay env-only tuning.
273273

274274
**CORE (10, always-on, cap- & eviction-exempt)** — defined in
275-
[`tool_bundles.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/chat/tool_bundles.py):
275+
[`tool_bundles.py`](https://github.com/amd/gaia/blob/main/hub/agents/python/chat/gaia_agent_chat/tool_bundles.py):
276276
`remember`, `recall`, `update_memory`, `forget`, `search_past_conversations`,
277277
`read_file`, `query_documents`, `query_specific_file`, `set_loop_state`,
278278
`request_user_input`.
@@ -351,7 +351,7 @@ baseline — meaning **CORE-only is the ~60%-reduction best case** and a full
351351
#### How Part 2 shipped (implementation reference)
352352

353353
**`load_tools` is always-on via CORE.** `load_tools` is added to
354-
[`DOC_CORE_TOOLS`](https://github.com/amd/gaia/blob/main/src/gaia/agents/chat/tool_bundles.py)
354+
[`DOC_CORE_TOOLS`](https://github.com/amd/gaia/blob/main/hub/agents/python/chat/gaia_agent_chat/tool_bundles.py)
355355
(CORE = 11), so once registered it renders in **both** the text prompt and the
356356
native `tools=` schema every active turn and is cap-/eviction-exempt. It is
357357
registered **only when the loader is active** (`self.tool_loader is not None`),
@@ -481,7 +481,7 @@ needs a seeded procedure matching a scenario goal.
481481
These were open in the design sketch; Part 1 (#1449) decided them as follows:
482482

483483
1. **Bundle definitions and CORE membership***decided.* CORE = 10 names and 12
484-
bundles, in [`tool_bundles.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/chat/tool_bundles.py)
484+
bundles, in [`tool_bundles.py`](https://github.com/amd/gaia/blob/main/hub/agents/python/chat/gaia_agent_chat/tool_bundles.py)
485485
(see [How Part 1 shipped](#part-1-selection-dual-path-filtering-landed-1449)),
486486
pinned to cover the 37-tool `doc` registry exactly.
487487
2. **Similarity threshold τ / cap***decided.* τ = `0.20` inclusive, cap = `14`

docs/playbooks/chat-agent/part-1-getting-started.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ Get a working agent running to understand the basic flow.
141141

142142
```python title="my_chat_agent.py"
143143
import json
144-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
144+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
145145

146146
# Create agent with a document
147147
config = ChatAgentConfig(
@@ -383,7 +383,7 @@ flowchart TD
383383
<CodeGroup>
384384
```python Example: Multiple Mixins
385385
from gaia.agents.base.agent import Agent
386-
from gaia.agents.chat.tools import RAGToolsMixin, FileToolsMixin
386+
from gaia.agents.tools import RAGToolsMixin, FileToolsMixin
387387

388388
class MyAgent(Agent, RAGToolsMixin, FileToolsMixin):
389389
def _register_tools(self):

docs/playbooks/chat-agent/part-2-advanced-features.mdx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Use GAIA's built-in mixins instead of implementing tools from scratch.
3030
```python step4_with_mixins.py
3131
from gaia.agents.base.agent import Agent
3232
from gaia.agents.base.console import AgentConsole
33-
from gaia.agents.chat.tools import RAGToolsMixin, FileToolsMixin
33+
from gaia.agents.tools import RAGToolsMixin, FileToolsMixin
3434
from gaia.agents.tools import FileSearchToolsMixin
3535
from gaia.rag.sdk import RAGSDK, RAGConfig
3636

@@ -101,7 +101,7 @@ agent.process_query("Find research papers in my Documents folder, index them, an
101101
- `list_indexed_documents()` - List currently indexed files
102102
- `rag_status()` - Get index statistics
103103

104-
**Import:** `from gaia.agents.chat.tools import RAGToolsMixin`
104+
**Import:** `from gaia.agents.tools import RAGToolsMixin`
105105
</Tab>
106106

107107
<Tab title="FileSearchToolsMixin">
@@ -117,7 +117,7 @@ agent.process_query("Find research papers in my Documents folder, index them, an
117117
**Directory monitoring:**
118118
- `add_watch_directory(directory)` - Monitor and auto-index changes
119119

120-
**Import:** `from gaia.agents.chat.tools import FileToolsMixin`
120+
**Import:** `from gaia.agents.tools import FileToolsMixin`
121121
</Tab>
122122

123123
<Tab title="Registration">
@@ -142,7 +142,7 @@ Add file system monitoring to automatically reindex documents when they change.
142142

143143
<CodeGroup>
144144
```python step5_with_monitoring.py
145-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
145+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
146146

147147
# The full ChatAgent includes file monitoring!
148148
config = ChatAgentConfig(
@@ -210,7 +210,7 @@ Implement session persistence to avoid re-indexing on every restart.
210210

211211
<CodeGroup>
212212
```python step6_create_session.py
213-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
213+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
214214

215215
config = ChatAgentConfig(
216216
rag_documents=["./manual.pdf"]
@@ -227,7 +227,7 @@ if agent.save_current_session():
227227
```
228228

229229
```python step6_load_session.py
230-
from gaia.agents.chat.agent import ChatAgent
230+
from gaia_agent_chat.agent import ChatAgent
231231

232232
agent = ChatAgent()
233233

@@ -288,7 +288,7 @@ The `ChatAgent` class combines all components. Here's how to configure and use i
288288
<Tabs>
289289
<Tab title="Full Configuration">
290290
```python title="complete_agent.py"
291-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
291+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
292292
from pathlib import Path
293293

294294
# Complete configuration
@@ -437,7 +437,7 @@ Extend the agent by adding domain-specific tools.
437437
<Tabs>
438438
<Tab title="Custom Tools">
439439
```python title="custom_tools.py"
440-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
440+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
441441
from gaia.agents.base.tools import tool
442442

443443
class CustomDocAgent(ChatAgent):
@@ -568,7 +568,7 @@ Override system prompts to create domain-specific behavior.
568568
<Tabs>
569569
<Tab title="Research Agent">
570570
```python title="research_agent.py"
571-
from gaia.agents.chat.agent import ChatAgent
571+
from gaia_agent_chat.agent import ChatAgent
572572

573573
class ResearchAgent(ChatAgent):
574574
"""Academic research specialist."""
@@ -591,7 +591,7 @@ Override system prompts to create domain-specific behavior.
591591

592592
<Tab title="Support Agent">
593593
```python title="support_agent.py"
594-
from gaia.agents.chat.agent import ChatAgent
594+
from gaia_agent_chat.agent import ChatAgent
595595

596596
class CustomerSupportAgent(ChatAgent):
597597
"""Customer support specialist."""
@@ -637,7 +637,7 @@ Override system prompts to create domain-specific behavior.
637637
<Tabs>
638638
<Tab title="Implementation">
639639
```python title="research_assistant.py"
640-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
640+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
641641
from pathlib import Path
642642

643643
research_folder = Path.home() / "Research" / "AI-Papers"
@@ -684,7 +684,7 @@ Override system prompts to create domain-specific behavior.
684684
<Tabs>
685685
<Tab title="Setup">
686686
```python title="knowledge_base.py"
687-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
687+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
688688
import os
689689

690690
docs_root = "/company/shared/documentation"
@@ -709,7 +709,7 @@ Override system prompts to create domain-specific behavior.
709709

710710
<Tab title="Team Usage">
711711
```python title="load_shared_session.py"
712-
from gaia.agents.chat.agent import ChatAgent
712+
from gaia_agent_chat.agent import ChatAgent
713713

714714
# Team member loads shared session
715715
agent = ChatAgent()
@@ -739,7 +739,7 @@ Override system prompts to create domain-specific behavior.
739739
<Tabs>
740740
<Tab title="Implementation">
741741
```python title="personal_assistant.py"
742-
from gaia.agents.chat.agent import ChatAgent, ChatAgentConfig
742+
from gaia_agent_chat.agent import ChatAgent, ChatAgentConfig
743743
from pathlib import Path
744744

745745
config = ChatAgentConfig(

0 commit comments

Comments
 (0)