|
9 | 9 |
|
10 | 10 | import os |
11 | 11 |
|
12 | | -from pydantic import SecretStr |
13 | | - |
14 | 12 | from openhands.sdk import ( |
15 | 13 | LLM, |
16 | 14 | Agent, |
|
26 | 24 | DelegateTool, |
27 | 25 | DelegationVisualizer, |
28 | 26 | ) |
29 | | -from openhands.tools.preset.default import get_default_tools |
| 27 | +from openhands.tools.preset.default import get_default_tools, register_builtins_agents |
30 | 28 |
|
31 | 29 |
|
32 | 30 | ONLY_RUN_SIMPLE_DELEGATION = False |
33 | 31 |
|
34 | 32 | logger = get_logger(__name__) |
35 | 33 |
|
36 | 34 | # Configure LLM and agent |
37 | | -# You can get an API key from https://app.all-hands.dev/settings/api-keys |
38 | | -api_key = os.getenv("LLM_API_KEY") |
39 | | -assert api_key is not None, "LLM_API_KEY environment variable is not set." |
40 | | -model = os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929") |
41 | 35 | llm = LLM( |
42 | | - model=model, |
43 | | - api_key=SecretStr(api_key), |
| 36 | + model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"), |
| 37 | + api_key=os.getenv("LLM_API_KEY"), |
44 | 38 | base_url=os.environ.get("LLM_BASE_URL", None), |
45 | 39 | usage_id="agent", |
46 | 40 | ) |
47 | 41 |
|
48 | 42 | cwd = os.getcwd() |
49 | 43 |
|
50 | | -register_tool("DelegateTool", DelegateTool) |
51 | | -tools = get_default_tools(enable_browser=False) |
52 | | -tools.append(Tool(name="DelegateTool")) |
| 44 | +tools = get_default_tools(enable_browser=True) |
| 45 | +tools.append(Tool(name=DelegateTool.name)) |
| 46 | +register_builtins_agents() |
53 | 47 |
|
54 | 48 | main_agent = Agent( |
55 | 49 | llm=llm, |
|
61 | 55 | visualizer=DelegationVisualizer(name="Delegator"), |
62 | 56 | ) |
63 | 57 |
|
64 | | -task_message = ( |
| 58 | +conversation.send_message( |
65 | 59 | "Forget about coding. Let's switch to travel planning. " |
66 | 60 | "Let's plan a trip to London. I have two issues I need to solve: " |
67 | 61 | "Lodging: what are the best areas to stay at while keeping budget in mind? " |
|
72 | 66 | "They should keep it short. After getting the results, merge both analyses " |
73 | 67 | "into a single consolidated report.\n\n" |
74 | 68 | ) |
75 | | -conversation.send_message(task_message) |
76 | 69 | conversation.run() |
77 | 70 |
|
78 | 71 | conversation.send_message( |
|
81 | 74 | conversation.run() |
82 | 75 |
|
83 | 76 | # Report cost for simple delegation example |
84 | | -cost_1 = conversation.conversation_stats.get_combined_metrics().accumulated_cost |
85 | | -print(f"EXAMPLE_COST (simple delegation): {cost_1}") |
| 77 | +cost_simple = conversation.conversation_stats.get_combined_metrics().accumulated_cost |
| 78 | +print(f"EXAMPLE_COST (simple delegation): {cost_simple}") |
86 | 79 |
|
87 | 80 | print("Simple delegation example done!", "\n" * 20) |
88 | 81 |
|
89 | | - |
90 | | -# -------- Agent Delegation Second Part: User-Defined Agent Types -------- |
91 | | - |
92 | 82 | if ONLY_RUN_SIMPLE_DELEGATION: |
| 83 | + # For CI: always emit the EXAMPLE_COST marker before exiting. |
| 84 | + print(f"EXAMPLE_COST: {cost_simple}") |
93 | 85 | exit(0) |
94 | 86 |
|
95 | 87 |
|
| 88 | +# -------- Agent Delegation Second Part: Built-in Agent Types (Explore + Bash) -------- |
| 89 | + |
| 90 | +main_agent = Agent( |
| 91 | + llm=llm, |
| 92 | + tools=[Tool(name=DelegateTool.name)], |
| 93 | +) |
| 94 | +conversation = Conversation( |
| 95 | + agent=main_agent, |
| 96 | + workspace=cwd, |
| 97 | + visualizer=DelegationVisualizer(name="Delegator (builtins)"), |
| 98 | +) |
| 99 | + |
| 100 | +builtin_task_message = ( |
| 101 | + "Demonstrate SDK built-in sub-agent types. " |
| 102 | + "1) Spawn an 'explore' sub-agent and ask it to list the markdown files in " |
| 103 | + "openhands-sdk/openhands/sdk/subagent/builtins/ and summarize what each " |
| 104 | + "built-in agent type is for (based on the file contents). " |
| 105 | + "2) Spawn a 'bash' sub-agent and ask it to run `python --version` in the " |
| 106 | + "terminal and return the exact output. " |
| 107 | + "3) Merge both results into a short report. " |
| 108 | + "Do not use internet access." |
| 109 | +) |
| 110 | + |
| 111 | +print("=" * 100) |
| 112 | +print("Demonstrating built-in agent delegation (explore + bash)...") |
| 113 | +print("=" * 100) |
| 114 | + |
| 115 | +conversation.send_message(builtin_task_message) |
| 116 | +conversation.run() |
| 117 | + |
| 118 | +# Report cost for builtin agent types example |
| 119 | +cost_builtin = conversation.conversation_stats.get_combined_metrics().accumulated_cost |
| 120 | +print(f"EXAMPLE_COST (builtin agents): {cost_builtin}") |
| 121 | + |
| 122 | +print("Built-in agent delegation example done!", "\n" * 20) |
| 123 | + |
| 124 | + |
| 125 | +# -------- Agent Delegation Third Part: User-Defined Agent Types -------- |
| 126 | + |
| 127 | + |
96 | 128 | def create_lodging_planner(llm: LLM) -> Agent: |
97 | 129 | """Create a lodging planner focused on London stays.""" |
98 | 130 | skills = [ |
@@ -190,10 +222,12 @@ def create_activities_planner(llm: LLM) -> Agent: |
190 | 222 | conversation.run() |
191 | 223 |
|
192 | 224 | # Report cost for user-defined agent types example |
193 | | -cost_2 = conversation.conversation_stats.get_combined_metrics().accumulated_cost |
194 | | -print(f"EXAMPLE_COST (user-defined agents): {cost_2}") |
| 225 | +cost_user_defined = ( |
| 226 | + conversation.conversation_stats.get_combined_metrics().accumulated_cost |
| 227 | +) |
| 228 | +print(f"EXAMPLE_COST (user-defined agents): {cost_user_defined}") |
195 | 229 |
|
196 | 230 | print("All done!") |
197 | 231 |
|
198 | 232 | # Full example cost report for CI workflow |
199 | | -print(f"EXAMPLE_COST: {cost_1 + cost_2}") |
| 233 | +print(f"EXAMPLE_COST: {cost_simple + cost_builtin + cost_user_defined}") |
0 commit comments