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
17 changes: 12 additions & 5 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,29 @@ Ensure you are running commands from the project root.

### API key not detected

**Problem**
Weft reports that no API key is available.
**Problem**
Docker Compose warns: `The "ANTHROPIC_API_KEY" variable is not set`

**Fix**

1. **Create .env file in project root:**
```bash
export ANTHROPIC_API_KEY=sk-ant-...
echo "ANTHROPIC_API_KEY=sk-ant-your-key" > .env
```

Restart the runtime after setting the key:
2. **Or export in shell:**
```bash
export ANTHROPIC_API_KEY=sk-ant-your-key
```

3. **Restart the runtime:**
```bash
weft down
weft up
```

**Note:** After running `weft init`, `.weft/.env.weft.common` should exist. If missing, run `weft init --force` to regenerate.

---

### Invalid configuration
Expand Down Expand Up @@ -146,7 +153,7 @@ Most commonly caused by missing API keys or Docker misconfiguration.

### Agents are not processing work

**Problem**
**Problem**
Agents start but no output is produced.

**Fix**
Expand Down
36 changes: 36 additions & 0 deletions src/weft/templates/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ services:
watcher-meta:
<<: *watcher-common
container_name: weft-watcher-meta
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_CODE_REPO_PATH=${CODE_REPO_PATH:-/tmp}
- WEFT_AI_HISTORY_PATH=${AI_HISTORY_PATH:-/tmp}
- AGENT_ID=meta
env_file:
- .env.weft.common
- agents/00-meta/.env
Expand All @@ -32,6 +38,12 @@ services:
watcher-architect:
<<: *watcher-common
container_name: weft-watcher-architect
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_CODE_REPO_PATH=${CODE_REPO_PATH:-/tmp}
- WEFT_AI_HISTORY_PATH=${AI_HISTORY_PATH:-/tmp}
- AGENT_ID=architect
env_file:
- .env.weft.common
- agents/01-architect/.env
Expand All @@ -40,6 +52,12 @@ services:
watcher-openapi:
<<: *watcher-common
container_name: weft-watcher-openapi
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_CODE_REPO_PATH=${CODE_REPO_PATH:-/tmp}
- WEFT_AI_HISTORY_PATH=${AI_HISTORY_PATH:-/tmp}
- AGENT_ID=openapi
env_file:
- .env.weft.common
- agents/02-openapi/.env
Expand All @@ -48,6 +66,12 @@ services:
watcher-ui:
<<: *watcher-common
container_name: weft-watcher-ui
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_CODE_REPO_PATH=${CODE_REPO_PATH:-/tmp}
- WEFT_AI_HISTORY_PATH=${AI_HISTORY_PATH:-/tmp}
- AGENT_ID=ui
env_file:
- .env.weft.common
- agents/03-ui/.env
Expand All @@ -56,6 +80,12 @@ services:
watcher-integration:
<<: *watcher-common
container_name: weft-watcher-integration
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_CODE_REPO_PATH=${CODE_REPO_PATH:-/tmp}
- WEFT_AI_HISTORY_PATH=${AI_HISTORY_PATH:-/tmp}
- AGENT_ID=integration
env_file:
- .env.weft.common
- agents/04-integration/.env
Expand All @@ -64,6 +94,12 @@ services:
watcher-test:
<<: *watcher-common
container_name: weft-watcher-test
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- WEFT_CODE_REPO_PATH=${CODE_REPO_PATH:-/tmp}
- WEFT_AI_HISTORY_PATH=${AI_HISTORY_PATH:-/tmp}
- AGENT_ID=test
env_file:
- .env.weft.common
- agents/05-test/.env
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/weft/cli/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pathlib import Path
from unittest.mock import Mock, patch

import yaml
from click.testing import CliRunner

from weft.cli.runtime import down, logs, up
Expand Down Expand Up @@ -542,3 +543,60 @@ def test_logs_from_subdirectory(
# Verify docker compose was called with correct path
call_args = mock_run.call_args[0][0]
assert "-f" in call_args


class TestDockerComposeTemplate:
"""Tests for docker-compose.yml template validation."""

def test_template_includes_agent_id_for_all_services(self):
"""Test that docker-compose template has AGENT_ID set for all watcher services."""
# Read the docker-compose template
template_path = (
Path(__file__).parent.parent.parent.parent.parent
/ "src"
/ "weft"
/ "templates"
/ "docker-compose.yml"
)
assert template_path.exists(), f"Template not found at {template_path}"

with open(template_path) as f:
compose_config = yaml.safe_load(f)

# Expected agents and their AGENT_ID values
expected_agents = {
"watcher-meta": "meta",
"watcher-architect": "architect",
"watcher-openapi": "openapi",
"watcher-ui": "ui",
"watcher-integration": "integration",
"watcher-test": "test",
}

# Verify each service has AGENT_ID environment variable
for service_name, expected_agent_id in expected_agents.items():
assert (
service_name in compose_config["services"]
), f"Service {service_name} not found in template"

service = compose_config["services"][service_name]
assert "environment" in service, f"Service {service_name} missing environment section"

env_list = service["environment"]
assert isinstance(
env_list, list
), f"Service {service_name} environment should be a list"

# Check if AGENT_ID is in the environment list
agent_id_found = False
for env_var in env_list:
if isinstance(env_var, str) and env_var.startswith("AGENT_ID="):
agent_id_value = env_var.split("=", 1)[1]
assert agent_id_value == expected_agent_id, (
f"Service {service_name} has AGENT_ID={agent_id_value}, "
f"expected AGENT_ID={expected_agent_id}"
)
agent_id_found = True
break

assert agent_id_found, f"Service {service_name} missing AGENT_ID environment variable"