Skip to content

Commit b81ee98

Browse files
committed
Add runner skill and show model
1 parent dbcaa28 commit b81ee98

3 files changed

Lines changed: 46 additions & 7 deletions

File tree

ensemble_agent/agent.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
async def run_agent(config: AgentConfig):
2727
"""Main entry point: build skills, connect MCP, run the agent loop."""
2828

29+
# Archive existing output dir before starting fresh
30+
ArchiveManager.archive_existing_output_dir(config.output_dir)
31+
2932
# Set up archive manager
3033
archive = ArchiveManager(config.output_dir)
3134

@@ -55,9 +58,9 @@ async def run_agent(config: AgentConfig):
5558
tools.extend(skill.get_tools())
5659

5760
# Create LLM and agent
58-
llm = create_llm(config.model, config.temperature, config.base_url)
61+
llm, service = create_llm(config.model, config.temperature, config.base_url)
5962
agent = create_agent(llm, tools)
60-
print("Agent initialized\n")
63+
print(f"Agent initialized (model: {config.model}, service: {service})\n")
6164

6265
# Build system prompt
6366
system_prompt = build_system_prompt(skills, has_generator)

ensemble_agent/llm.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,39 @@
44
import sys
55

66

7+
def _service_label(model, base_url):
8+
"""Determine the service name from model and base_url."""
9+
if "claude" in model.lower():
10+
anthropic_base = os.environ.get("ANTHROPIC_BASE_URL", "")
11+
if "anl.gov" in anthropic_base or "argo" in anthropic_base.lower():
12+
return "Argo"
13+
return "Anthropic"
14+
if base_url:
15+
if "anl.gov" in base_url or "argo" in base_url.lower():
16+
return "Argo"
17+
if "alcf" in base_url.lower():
18+
return "ALCF"
19+
return f"OpenAI-compatible ({base_url})"
20+
return "OpenAI"
21+
22+
723
def create_llm(model, temperature=0, base_url=None):
8-
"""Create LLM — ChatAnthropic for Claude models, ChatOpenAI otherwise."""
24+
"""Create LLM — ChatAnthropic for Claude models, ChatOpenAI otherwise.
25+
26+
Returns (llm, service_label).
27+
"""
28+
service = _service_label(model, base_url)
929
if "claude" in model.lower():
1030
try:
1131
from langchain_anthropic import ChatAnthropic
1232
except ImportError:
1333
sys.exit("Error: pip install langchain-anthropic required for Claude models")
1434
anthropic_base = os.environ.get("ANTHROPIC_BASE_URL")
15-
return ChatAnthropic(
35+
llm = ChatAnthropic(
1636
model=model, temperature=temperature, base_url=anthropic_base or None,
1737
streaming=True,
1838
)
39+
return llm, service
1940
from langchain_openai import ChatOpenAI
2041

21-
return ChatOpenAI(model=model, temperature=temperature, base_url=base_url)
42+
return ChatOpenAI(model=model, temperature=temperature, base_url=base_url), service

ensemble_agent/skills/runner.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from langchain_core.tools import StructuredTool
77

88
from .base import Skill
9+
from ..config import MAX_RETRIES
910

1011

1112
class RunScriptInput(BaseModel):
@@ -15,17 +16,29 @@ class RunScriptInput(BaseModel):
1516
class RunnerSkill(Skill):
1617
"""Provides the run_script tool."""
1718

19+
def __init__(self, config, archive):
20+
super().__init__(config, archive)
21+
self._run_count = 0
22+
self._max_runs = config.max_retries + 1 # initial run + retries
23+
1824
def get_tools(self):
1925
work_dir = self.archive.work_dir
2026
archive = self.archive
2127
timeout = self.config.script_timeout
28+
skill = self
2229

2330
async def run_script_tool(script_name: str) -> str:
31+
skill._run_count += 1
32+
if skill._run_count > skill._max_runs:
33+
msg = f"RUN LIMIT REACHED ({skill._max_runs} runs). Stop and report the current status to the user."
34+
print(f"\n{msg}", flush=True)
35+
return msg
36+
2437
script_path = work_dir / script_name
2538
if not script_path.exists():
2639
return f"ERROR: Script '{script_name}' not found"
2740

28-
print(f"\nRunning {script_name}...", flush=True)
41+
print(f"\nRunning {script_name}... (run {skill._run_count}/{skill._max_runs})", flush=True)
2942
try:
3043
result = subprocess.run(
3144
["python", script_name],
@@ -45,10 +58,12 @@ async def run_script_tool(script_name: str) -> str:
4558
)
4659
print(f"Failed (code {result.returncode})", flush=True)
4760
archive.archive_run_output(error_msg)
61+
remaining = skill._max_runs - skill._run_count
4862
return (
4963
f"FAILED (code {result.returncode})\n"
5064
f"Stderr:\n{result.stderr}\n"
51-
f"Stdout:\n{result.stdout[:500]}"
65+
f"Stdout:\n{result.stdout[:500]}\n"
66+
f"\nYou have {remaining} run(s) remaining."
5267
)
5368
except subprocess.TimeoutExpired:
5469
return f"ERROR: Script timed out ({timeout}s)"

0 commit comments

Comments
 (0)