botWebWars/diagram_agent_gear.md

170 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# botagent_gear Architecture & Workflow Diagrams
This document outlines the system architecture, component relationships, and decision workflows of **`botagent_gear`**, the Google Cloud Vertex AI (Gemini) autonomous agent for **botWebWars**.
---
## 1. System Architecture Diagram
```mermaid
graph TB
subgraph HostEnv["Environment & Configuration"]
ENV["CLI Flags & Environment Variables<br/>(BOT_SERVER_URL, VERTEX_MODEL, etc.)"]
AUTH_SRC["Auth Sources<br/>(ADC / gcloud / Service Account / API Key)"]
end
subgraph BotAgentGear["botagent_gear (bot.py)"]
subgraph ClientLayer["LLM & Authentication Subsystem"]
VGC["VertexGeminiClient<br/>Token cache, auth check, endpoint routing"]
AUTH_RESOLV["Auth Resolver<br/>google.auth / gcloud CLI / API Key"]
PROMPT_ENG["Prompt & Payload Builder<br/>System Instructions + JSON Schema Mode"]
JSON_PARSE["extract_json<br/>Markdown stripping & JSON validation"]
end
subgraph CoreAgent["VertexAIBotAgent Subsystem"]
RUN_LOOP["Turn Polling Loop<br/>GET /api/turn"]
PERCEPTION["Perception Engine<br/>• Radar targets (distance, party, strength)<br/>• Available moves & diagonal squeeze cost<br/>• _build_local_map (17x17 ASCII minimap)"]
subgraph StrategyEngine["Decision & Rules Engine"]
ENCOUNTER["Encounter Evaluator<br/>_handle_adjacent_encounter"]
RULES_GUARD["Mandatory Rules Enforcer<br/>(GAME_RULES.md: forced joins & battles)"]
LLM_ALLIANCE["Voluntary Alliance Reasoner<br/>_decide_voluntary_alliance (Gemini)"]
LLM_NAV["Tactical Navigation Reasoner<br/>_ask_llm_for_direction (Gemini)"]
FALLBACK["Guardrail / Fallback Pathing<br/>Server recommended or nearest distance"]
end
ACTIONS["Action Dispatcher<br/>• Move bot (/move)<br/>• Form party (/parties)<br/>• Initiate battle (/battles/fight)<br/>• Pass turn (/pass)"]
end
end
subgraph ExternalBackends["External Services"]
SERVER["botWebWars Backend (FastAPI)<br/>Port 8000 REST API"]
GEMINI["Google Vertex AI / AI Studio<br/>gemini-2.5-flash / gemini-3.8-flash"]
end
%% Wiring
ENV --> CoreAgent
AUTH_SRC --> AUTH_RESOLV
AUTH_RESOLV --> VGC
VGC --> PROMPT_ENG
PROMPT_ENG --> GEMINI
GEMINI --> JSON_PARSE
JSON_PARSE --> VGC
RUN_LOOP --> SERVER
RUN_LOOP --> PERCEPTION
PERCEPTION --> SERVER
PERCEPTION --> StrategyEngine
StrategyEngine --> VGC
LLM_ALLIANCE -.-> VGC
LLM_NAV -.-> VGC
StrategyEngine --> ACTIONS
RULES_GUARD --> ACTIONS
FALLBACK --> ACTIONS
ACTIONS --> SERVER
```
---
## 2. Turn Execution & Tactical Decision Flow
```mermaid
flowchart TD
Start(["Turn Polled (bot's turn)"]) --> Refresh["refresh_status & fetch Radar Data"]
Refresh --> CheckAdj{"Adjacent hostile / neutral<br/>target within distance <= 1?"}
%% Adjacent Target Path
CheckAdj -- Yes --> SoloCheck{"Is current bot Solo?"}
SoloCheck -- "Yes (Solo)" --> TargetPartyCheck{"Is target in a Party?"}
TargetPartyCheck -- "No (Target is Solo)" --> GeminiAlliance["Query Gemini via ask_json<br/>(Voluntary Alliance)"]
GeminiAlliance --> AllianceChoice{"Form Alliance?"}
AllianceChoice -- Yes --> FormParty["POST /api/parties<br/>(Higher strength leads)"]
AllianceChoice -- No --> Pass1["POST /api/players/{id}/pass"]
TargetPartyCheck -- "Yes (Target in Party)" --> CompareLeaderStr{"Bot Strength <= Target Leader Strength?"}
CompareLeaderStr -- Yes --> JoinSquad["Move into squad<br/>(Voluntary absorption)"]
CompareLeaderStr -- No --> FightParty["POST /api/battles/fight<br/>(Mandatory battle: refused weak leader)"]
SoloCheck -- "No (In Party)" --> LeaderCheck{"Is bot the Party Leader?"}
LeaderCheck -- No --> PassFollower["POST /api/players/{id}/pass<br/>(Follow leader command)"]
LeaderCheck -- Yes --> PartyVsTarget{"Target has Party?"}
PartyVsTarget -- Yes --> FightHostile["POST /api/battles/fight<br/>(Mandatory squad battle)"]
PartyVsTarget -- No --> SoloTargetStr{"Solo target <= Leader Strength?"}
SoloTargetStr -- Yes --> AbsorbSolo["Step toward target<br/>(Absorb solo follower)"]
SoloTargetStr -- No --> FightSolo["POST /api/battles/fight<br/>(Mandatory battle: solo refused)"]
%% Navigation Path
CheckAdj -- No --> FetchMoves["Fetch available moves & Board snapshot"]
FetchMoves --> GenMap["_build_local_map<br/>(Generate 17x17 ASCII minimap)"]
GenMap --> AskNav["Query Gemini via ask_json<br/>(Direction & Reasoning)"]
AskNav --> ValidChoice{"Chosen direction in legal moves?"}
ValidChoice -- Yes --> ExecMove["POST /api/players/{id}/move"]
ValidChoice -- No --> FallbackMove["Fallback: Server recommended or nearest distance"]
FallbackMove --> ExecMove
%% Outcome
FormParty --> CheckEnd["Check Game Conclusion"]
Pass1 --> CheckEnd
JoinSquad --> CheckEnd
FightParty --> CheckEnd
PassFollower --> CheckEnd
FightHostile --> CheckEnd
AbsorbSolo --> CheckEnd
FightSolo --> CheckEnd
ExecMove --> CheckEnd
CheckEnd --> Done(["End of Turn"])
```
---
## 3. Component Deep Dive
### A. Authentication & LLM Client (`VertexGeminiClient`)
- **Module**: [`bot.py`](file:///home/isaac/Workspaces/botWebWars/botagent_gear/bot.py#L82-L269)
- **Multi-Auth Strategy**:
1. `google-auth` Python library using Application Default Credentials (ADC).
2. `gcloud CLI` fallback via `gcloud auth print-access-token`.
3. Direct OAuth token (`VERTEX_ACCESS_TOKEN` or `GOOGLE_OAUTH_ACCESS_TOKEN`).
4. Service Account JSON key (`GOOGLE_APPLICATION_CREDENTIALS`).
5. Direct Gemini API Key (`GEMINI_API_KEY` or `VERTEX_API_KEY`) routing to Google AI Studio.
- **Token Caching**: Access tokens are cached for up to 50 minutes with automatic invalidation and single-retry on HTTP 401.
- **Structured JSON Mode**: Uses `generationConfig.responseMimeType = "application/json"` with low temperature (`0.3`) for deterministic schema adherence.
### B. Perception Engine & Spatial Representation
- **Minimap Generator** ([`_build_local_map`](file:///home/isaac/Workspaces/botWebWars/botagent_gear/bot.py#L542-L574)):
- Generates a **17 × 17 ASCII grid** centered on the bot (`radius = 8`).
- Legend: `@` = self, `A` = ally, `E` = enemy/neutral, `M` = mountain, `F` = forest, `V` = valley, `#` = boundary, `.` = open terrain.
- **Radar & Move Analysis**:
- Consumes `/api/players/{id}/radar` for target distance and party alignment.
- Consumes `/api/players/{id}/available-moves` to account for diagonal obstacle squeeze penalties (`-0.1` solo, `-0.2` leader / `-0.1` follower).
### C. Hybrid Decision & Rules Engine
- **Deterministic Rules Enforcer**:
- Implements canonical rules from [GAME_RULES.md](file:///home/isaac/Workspaces/botWebWars/GAME_RULES.md).
- Mandatory battles and joins bypass LLM invocation to guarantee engine compliance.
- **LLM Discretionary Invocations**:
- **Voluntary Alliances**: Solo bot meetings prompt Gemini to weigh party leadership vs. squad safety.
- **Tactical Navigation**: Coordinates obstacle avoidance, frontier exploration, and hostile avoidance using the local minimap and radar summary.
---
## 4. Backend REST API Interactions
| Method | Endpoint | Usage in `botagent_gear` |
|---|---|---|
| `POST` | `/api/players` | Register bot avatar or reconnect existing avatar |
| `GET` | `/api/players/{id}` | Refresh player health, score, and party leader status |
| `GET` | `/api/turn` | Turn polling loop to detect active player and round |
| `GET` | `/api/players/{id}/radar` | Scans surrounding bots and nearest target |
| `GET` | `/api/players/{id}/available-moves` | Evaluates passable directions & diagonal squeeze penalties |
| `GET` | `/api/board` | Full board snapshot for ASCII minimap generation |
| `POST` | `/api/players/{id}/move` | Execute cardinal / diagonal movement |
| `POST` | `/api/parties` | Establish voluntary alliance party |
| `POST` | `/api/battles/fight` | Initiate tactical 3-bout D20 confrontation |
| `POST` | `/api/players/{id}/pass` | Yield turn (follower wait or skipped turn) |
| `GET` | `/api/game/conclusion` | Check if single party remains (victory condition) |
| `DELETE` | `/api/players/{id}` | Clean disconnection on `SIGINT` / Ctrl+C |