Skip to content

Commit 8e465f4

Browse files
Merge pull request #17 from contextualizer-ai/compare-across-agents
Experiment 1: Cross-Agent Comparison Infrastructure
2 parents 9b21bc8 + 47ddcfa commit 8e465f4

52 files changed

Lines changed: 31018 additions & 149 deletions

Some content is hidden

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

.github/workflows/main.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,9 @@ jobs:
5151
- name: Install project
5252
run: uv sync --dev
5353

54+
- name: Install goose
55+
run: |
56+
curl -fsSL https://github.com/block/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash
57+
5458
- name: Run test suite
5559
run: just test

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ tests/*/*/output
44

55
# temp files
66
tmp/
7+
workdir/
8+
eval_workdir/
9+
10+
# DeepEval cache
11+
.deepeval/
12+
13+
# Compare agents evaluation results (large YAML files)
14+
results/compare_agents/
15+
16+
# Attic for old evaluation results
17+
results/attic/
718

819
# Byte-compiled / optimized / DLL files
920
__pycache__/

CLAUDE.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,39 @@ NEVER required, if you think you need them, it's likely a bad smell that your lo
6868
2. All commands are run through `just` or `uv run`
6969
3. The project uses dynamic versioning from git tags
7070
4. Documentation is auto-deployed to GitHub Pages at https://monarch-initiative.github.io/my-awesome-tool
71+
72+
---
73+
74+
## EVALUATION MODE: Answering Literature Retrieval Questions
75+
76+
**When you receive questions about scientific papers** (e.g., "What is the title of PMID:12345?"), you are in **evaluation mode**. This is testing MCP server performance.
77+
78+
### Guidelines for Evaluation Mode:
79+
80+
1. **Use the MCP tools** available to retrieve the requested paper
81+
- Try `mcp__artl__get_pmid_text` or similar MCP tools
82+
- Don't assume content is inaccessible - try the MCPs first
83+
84+
2. **Answer from what the MCP retrieved**
85+
- If the MCP successfully returns content, extract the requested information
86+
- Don't say "I cannot access" if the MCP gave you the content
87+
- Don't add unnecessary commentary about paper relevance or domain
88+
89+
3. **Be direct and precise**
90+
- Extract exactly what was asked for (title, sentence, table row, etc.)
91+
- Match the expected format when possible
92+
- Provide just the answer, not explanations about why you can/can't answer
93+
94+
4. **Do NOT restrict by topic**
95+
- Answer questions about ANY paper, regardless of subject area
96+
- Don't reject papers because they're "not about X domain"
97+
- The evaluation covers diverse scientific literature
98+
99+
### Example - Good Response:
100+
**Q**: "What is the first sentence of section 2 in PMID:28027860?"
101+
**A**: "Even though many of NFLE's core features have been clarified in the last two decades, some critical issues remain controversial."
102+
103+
### Example - Bad Response:
104+
**Q**: "What is the first sentence of section 2 in PMID:28027860?"
105+
**A**: "I cannot access section 2 of this paper because it's behind a paywall and not available in open access..."
106+
*(Bad because: If the MCP retrieved it, you DO have access - answer from what was retrieved!)*

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ modification, are permitted provided that the following conditions are met:
1111
this list of conditions and the following disclaimer in the documentation
1212
and/or other materials provided with the distribution.
1313

14-
* Neither the name of pytest-mcp_literature_eval nor the names of its
14+
* Neither the name of mcp_literature_eval nor the names of its
1515
contributors may be used to endorse or promote products derived from
1616
this software without specific prior written permission.
1717

METACODER_FIXES.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Metacoder Goose Coder Fixes
2+
3+
## Summary
4+
5+
Fixed systematic failures in Goose evaluations (100% failure rate with exit code 101) by properly configuring environment variables and adding error handling to the GooseCoder implementation.
6+
7+
## Problem
8+
9+
Goose evaluations were failing immediately with:
10+
- Exit code 101
11+
- Execution time: 0.02-0.06 seconds (indicating immediate crash)
12+
- 100% failure rate across all 100 tests
13+
14+
## Root Causes
15+
16+
1. **Missing environment variable configuration**: Goose requires `GOOSE_PROVIDER__API_KEY` (double underscore) but metacoder was not setting it
17+
2. **Config precedence issues**: Global `~/.config/goose/config.yaml` settings were overriding local evaluation configs
18+
3. **Missing error handling**: Process failures crashed the entire evaluation instead of marking individual tests as failed
19+
4. **Problematic global extensions**: Global config had extensions enabled that didn't exist in evaluation workdirs
20+
21+
## Solutions Implemented
22+
23+
### 1. Environment Variable Configuration
24+
25+
**File**: `.venv/lib/python3.10/site-packages/metacoder/coders/goose.py`
26+
27+
**Location**: Lines 193-217 in the `run()` method
28+
29+
**Changes**:
30+
```python
31+
# Override provider and model from config via environment variables
32+
# This ensures local settings take precedence over global config
33+
if self.config and self.config.ai_model:
34+
model = self.config.ai_model
35+
# Get provider as string
36+
if isinstance(model.provider, str):
37+
provider_str = model.provider
38+
elif model.provider and hasattr(model.provider, "name"):
39+
provider_str = model.provider.name
40+
else:
41+
provider_str = "openai" # default
42+
43+
env["GOOSE_PROVIDER"] = provider_str
44+
env["GOOSE_MODEL"] = model.name
45+
logger.debug(f"Setting GOOSE_PROVIDER={provider_str}, GOOSE_MODEL={model.name}")
46+
47+
# Set API key via GOOSE_PROVIDER__API_KEY environment variable
48+
# Check for provider-specific API keys in environment
49+
if provider_str == "anthropic" and "ANTHROPIC_API_KEY" in env:
50+
env["GOOSE_PROVIDER__API_KEY"] = env["ANTHROPIC_API_KEY"]
51+
logger.debug("Set GOOSE_PROVIDER__API_KEY from ANTHROPIC_API_KEY")
52+
elif provider_str == "openai" and "OPENAI_API_KEY" in env:
53+
env["GOOSE_PROVIDER__API_KEY"] = env["OPENAI_API_KEY"]
54+
logger.debug("Set GOOSE_PROVIDER__API_KEY from OPENAI_API_KEY")
55+
```
56+
57+
**Why this fixes the issue**:
58+
- Goose uses `GOOSE_PROVIDER__API_KEY` (double underscore) as the standard API key environment variable
59+
- Setting `GOOSE_PROVIDER` and `GOOSE_MODEL` as environment variables ensures they override global config
60+
- Maps provider-specific keys (ANTHROPIC_API_KEY, OPENAI_API_KEY) to Goose's expected format
61+
62+
### 2. Error Handling
63+
64+
**File**: `.venv/lib/python3.10/site-packages/metacoder/coders/goose.py`
65+
66+
**Location**: Lines 223-239 in the `run()` method
67+
68+
**Changes**:
69+
```python
70+
try:
71+
result = self.run_process(command, env)
72+
end_time = time.time()
73+
ao = CoderOutput(stdout=result.stdout, stderr=result.stderr)
74+
logger.info(f"🦆 Command took {end_time - start_time:.2f} seconds")
75+
except Exception as e:
76+
# Handle process errors gracefully - don't crash entire evaluation
77+
end_time = time.time()
78+
logger.warning(f"Goose command failed (test will be marked as failed): {e}")
79+
ao = CoderOutput(
80+
stdout="",
81+
stderr=str(e),
82+
result_text=f"Error: {str(e)}",
83+
success=False,
84+
)
85+
logger.info(f"🦆 Command took {end_time - start_time:.2f} seconds")
86+
return ao
87+
```
88+
89+
**Why this fixes the issue**:
90+
- Prevents single test failures from crashing the entire evaluation
91+
- Gracefully handles process errors and marks individual tests as failed
92+
- Allows evaluation to continue through all 100 tests
93+
94+
### 3. Global Config Fixes
95+
96+
**File**: `~/.config/goose/config.yaml`
97+
98+
**Change**: Disabled problematic `tabfilequery` extension
99+
100+
```yaml
101+
tabfilequery:
102+
enabled: false # Changed from true
103+
```
104+
105+
**Why this was needed**:
106+
- The global config had `tabfilequery` extension enabled
107+
- This extension tried to run `src/fitness_mcp/main.py` which doesn't exist in evaluation workdirs
108+
- Caused Goose to fail on startup
109+
110+
## Results
111+
112+
**Before fixes**:
113+
- 100/100 tests failing (exit code 101)
114+
- Test duration: 0.02-0.06 seconds (immediate crash)
115+
- No results generated
116+
117+
**After fixes**:
118+
- 100/100 tests completed successfully (exit code 0)
119+
- Test duration: 10-24 seconds (proper execution)
120+
- Results file generated: `goose_20251101.yaml` (919KB, 18,595 lines)
121+
- Average score: 0.137 (~13.7%)
122+
123+
## Files Modified
124+
125+
1. **`.venv/lib/python3.10/site-packages/metacoder/coders/goose.py`**
126+
- Added environment variable configuration (lines 193-217)
127+
- Added error handling (lines 223-239)
128+
129+
2. **`~/.config/goose/config.yaml`**
130+
- Disabled `tabfilequery` extension (line 132)
131+
132+
## Testing
133+
134+
Verified with:
135+
```bash
136+
export OPENAI_API_KEY=$(cat ~/openai.key)
137+
export ANTHROPIC_API_KEY=$(cat ~/anthropic.key)
138+
uv run metacoder eval project/literature_mcp_eval_config.yaml -o results/raw/goose_20251101.yaml
139+
```
140+
141+
Result: All 100 tests completed successfully.
142+
143+
### Error 4: MCP extensions not loading (CRITICAL)
144+
145+
**Problem**: All 100 Goose tests showed "No extensions available to enable" even though extensions were configured in `.config/goose/config.yaml`.
146+
147+
**Root cause discovered**: `goose run` command DOES NOT load extensions from config files. Extensions must be passed as command-line arguments using `--with-extension`.
148+
149+
**Fix**: Modified `goose.py` lines 221-232 to add `--with-extension` flags for each configured MCP extension:
150+
151+
```python
152+
# Add MCP extensions as command-line arguments
153+
# Config files alone don't work with 'goose run' - must use --with-extension
154+
if self.config and self.config.extensions:
155+
for mcp in self.config.extensions:
156+
if isinstance(mcp, MCPConfig) and mcp.enabled:
157+
# Build extension command from cmd + args
158+
if mcp.command:
159+
ext_cmd = mcp.command
160+
if mcp.args:
161+
ext_cmd = ext_cmd + " " + " ".join(mcp.args)
162+
command.extend(["--with-extension", ext_cmd])
163+
logger.debug(f"Adding extension: --with-extension {ext_cmd}")
164+
```
165+
166+
**Example**: For an extension configured as:
167+
```yaml
168+
extensions:
169+
artl:
170+
cmd: uvx
171+
args:
172+
- artl-mcp
173+
```
174+
175+
The command now becomes:
176+
```bash
177+
goose run -t "text" --with-extension "uvx artl-mcp"
178+
```
179+
180+
**Verification**:
181+
- Before fix: "I don't currently have access to any extensions"
182+
- After fix: Goose successfully calls MCP tools like `get_paper`, `get_metadata`, etc.
183+
184+
**Reference**: https://block.github.io/goose/docs/guides/goose-cli-commands/ documents the `--with-extension` flag.
185+
186+
## Upstream Contribution
187+
188+
The changes to `goose.py` should be contributed back to the metacoder project as they fix critical bugs that prevent Goose evaluations from working:
189+
190+
1. Missing `GOOSE_PROVIDER__API_KEY` environment variable configuration
191+
2. MCP extensions not being passed to `goose run` command via `--with-extension` flags
192+
3. Crash-on-error bug that prevented graceful failure handling
193+
194+
### Patch File
195+
196+
A patch file has been created: `metacoder_goose_error_handling.patch`
197+
198+
### Recommended Next Steps
199+
200+
1. Submit a PR to the metacoder repository with these fixes
201+
2. Include all three fixes: environment variables, extension command-line args, and error handling
202+
3. Add documentation about:
203+
- Goose's environment variable requirements (`GOOSE_PROVIDER__API_KEY`)
204+
- How `goose run` requires `--with-extension` flags (config files are not sufficient)

0 commit comments

Comments
 (0)