Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .claude/context/nats-subjects.md
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,73 @@ nats server report connections
- `nats_server_messages_in` - Messages received
- `nats_server_messages_out` - Messages sent

## AgentGym RL Training Subjects

### Training Lifecycle

**`agentgym.train.started.v1`**
- **Direction:** Published by EvoSwarm (evo-controller) → Consumed by AgentGym-RL coordinator, monitoring
- **Purpose:** Notify that RL training has been triggered
- **Payload:**
```json
{
"training_run_id": "run-abc123",
"environment": "pmoves-hirag",
"trigger_reason": "fitness_plateau|new_constellation|scheduled|fitness_degradation",
"population_id": "pop-5",
"algorithm": "ppo|grpo|rloo|reinforce++",
"horizon": 10,
"num_epochs": 25,
"learning_rate": 1e-6,
"geometry_config": {
"cgp_fitness_weight": 0.2,
"retrieval_quality_weight": 0.3,
"task_success_weight": 0.4
},
"timestamp": "2026-03-14T12:00:00Z"
}
```
- **Subscribers:** AgentGym-RL coordinator, observability dashboards

**`agentgym.train.completed.v1`**
- **Direction:** Published by EvoSwarm (evo-controller) → Consumed by AgentGym-RL coordinator
- **Purpose:** Training run finished — triggers auto-publish to HuggingFace Hub
- **Payload:**
```json
{
"training_run_id": "run-abc123",
"trajectory_ids": ["traj-1", "traj-2"],
"model_id": "Qwen3-8B-Instruct",
"population_id": "pop-5",
"fitness_metrics": {
"avg_reward": 0.82,
"task_success_rate": 0.91,
"retrieval_quality": 0.78
},
"epoch": 50,
"generation": 5,
"timestamp": "2026-03-14T14:00:00Z"
}
```
- **Subscribers:** AgentGym-RL coordinator (auto-publishes to HF), monitoring
- **Triggers:** `agentgym.model.published.v1`, `skills.pipeline.model-benchmark-viz.v1`

**`agentgym.model.published.v1`**
- **Direction:** Published by AgentGym-RL coordinator → Consumed by monitoring, Agent Zero
- **Purpose:** Model/dataset published to HuggingFace Hub
- **Payload:**
```json
{
"training_run_id": "run-abc123",
"model_id": "Qwen3-8B-Instruct",
"dataset_id": "pmoves/agentgym-run-abc123",
"repo_url": "https://huggingface.co/datasets/pmoves/agentgym-run-abc123",
"trajectory_count": 15,
"source": "agentgym-rl-coordinator"
}
```
- **Subscribers:** Agent Zero, Discord Publisher, observability dashboards

## BoTZ MCP GitHub Subjects

### GitHub Tool Execution
Expand Down
6 changes: 5 additions & 1 deletion pmoves/env.agentgym.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ AGENTGYM_ENABLE=true
AGENTGYM_COORDINATOR_URL=http://agentgym-rl-coordinator:8114

# Base model for agent training (HuggingFace model ID or local path)
AGENTGYM_BASE_MODEL=Qwen2.5-7B-Instruct
AGENTGYM_BASE_MODEL=Qwen/Qwen3-8B

# HuggingFace Hub credentials (required for dataset publishing)
HF_TOKEN= # Your HuggingFace API token
HF_ORG=pmoves # HuggingFace organization for published datasets
Comment thread
POWERFULMOVES marked this conversation as resolved.

# Model storage path (Docker volume mount)
AGENTGYM_MODEL_PATH=/models
Expand Down
24 changes: 20 additions & 4 deletions pmoves/services/agentgym-rl-coordinator/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import re
import asyncio
from contextlib import asynccontextmanager
from datetime import datetime, timezone
from typing import Optional
from uuid import UUID
from fastapi import FastAPI, HTTPException
Expand Down Expand Up @@ -142,7 +143,7 @@ async def hf_model_handler(msg):
async def training_completed_handler(msg):
"""
Handle a training completion event by optionally publishing associated trajectories to HuggingFace, emitting related NATS events, and recording the completion in storage.

Parameters:
msg: NATS message whose `data` is a JSON-encoded payload containing at minimum a `training_run_id` and optionally `trajectory_ids` and `model_id`.
"""
Expand All @@ -156,11 +157,25 @@ async def training_completed_handler(msg):
logger.warning("agentgym.train.completed.v1 missing training_run_id")
return

if not DATASET_NAME_PATTERN.match(training_run_id):
logger.warning("Invalid training_run_id format: %s", training_run_id[:100])
return

logger.info(
"Training completed: run=%s, trajectories=%d, model=%s",
training_run_id, len(trajectory_ids), model_id,
)

# Validate trajectory IDs as UUIDs before publishing
valid_trajectory_ids = []
for tid in trajectory_ids:
try:
UUID(tid)
valid_trajectory_ids.append(tid)
except (ValueError, AttributeError):
logger.warning("Skipping invalid trajectory_id: %s", str(tid)[:100])
trajectory_ids = valid_trajectory_ids

# Auto-publish to HuggingFace if publisher is available
if hf_publisher and trajectory_ids:
dataset_name = f"agentgym-{training_run_id}"
Expand All @@ -184,6 +199,7 @@ async def training_completed_handler(msg):
"repo_url": result.get("repo_url"),
"trajectory_count": len(trajectory_ids),
"source": "agentgym-rl-coordinator",
"timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
})
await nc.publish(
"agentgym.model.published.v1",
Expand Down Expand Up @@ -537,11 +553,11 @@ async def publish_dataset(
for tid in trajectory_ids:
try:
UUID(tid)
except ValueError:
except ValueError as e:
raise HTTPException(
status_code=400,
detail=f"Invalid trajectory_id format: {tid}. Must be a valid UUID."
)
detail=f"Invalid trajectory_id format: {tid}. Must be a valid UUID.",
) from e

if not hf_publisher:
raise HTTPException(status_code=503, detail="HuggingFace publisher not available")
Expand Down
8 changes: 4 additions & 4 deletions pmoves/services/evo-controller/agentgym_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ async def launch_agentgym_training(
if not decision.get("should_train"):
return None

base_model = os.getenv("AGENTGYM_BASE_MODEL", "Qwen3-8B-Instruct")
base_model = os.getenv("AGENTGYM_BASE_MODEL", "Qwen/Qwen3-8B")
env_namespace = os.getenv("AGENTGYM_ENV_NAMESPACE", "pmoves.consciousness")

# Build training request
Expand Down Expand Up @@ -360,16 +360,16 @@ async def on_training_completed(
) -> None:
"""
Publish a training completion event to the agent-zero event bus.

Sends an event with training metadata so downstream services (AgentGym-RL coordinator, publishing workflows) can process the completed run. The emitted payload includes training_run_id, trajectory_ids, model_id (resolved from the provided value or environment), population_id, fitness_metrics, epoch, generation, and an ISO-8601 UTC timestamp. On success the method logs the publication; on failure it logs a warning.

Parameters:
training_run_id (str): Identifier of the completed training run.
trajectory_ids (List[str]): List of trajectory identifiers produced by the run.
model_id (Optional[str]): Model identifier used for training; if omitted, the base model is resolved from environment variables or a default.
fitness_metrics (Optional[Dict[str, float]]): Final fitness metrics collected from the training; an empty dict is sent if omitted.
"""
base_model = model_id or os.getenv("AGENTGYM_BASE_MODEL", "Qwen3-8B-Instruct")
base_model = model_id or os.getenv("AGENTGYM_BASE_MODEL", "Qwen/Qwen3-8B")
base = os.getenv("AGENT_ZERO_BASE_URL") or os.getenv("AGENTZERO_BASE_URL") or "http://agent-zero:8080"
url = f"{base.rstrip('/')}/events/publish"

Expand Down
Loading