Commit 6fbf5fc
Update close tool + add output to agent result (#1505)
# Why
Previously, agent executions could end without a structured final
response - either by hitting `maxSteps` or the LLM breaking out of its
loop without calling the `close` tool. This made it difficult to:
1. Reliably determine if a task was completed successfully
2. Extract structured data from the agent's execution
# What Changed
### Ensured Close Tool is Always Called
- Added `handleCloseToolCall` utility that forces a `close` tool call
via a separate `generateText` call when the main agent loop ends without
explicitly closing
- Integrated via new `ensureClosed` private method in
`v3AgentHandler.ts`
- Works for both `execute()` and `stream()` modes
- Triggers when `maxSteps` is reached or the LLM stops ( completes its
task)
### Added Output Schema Support (Experimental)
- Users can now pass a Zod schema to `agent.execute({ output:
z.object({...}) })` to return structured data at the end of execution
- The schema dynamically extends the close tool's input schema
- Extracted data is returned in `result.output`
- Added validation:
- **CUA mode**: Throws `StagehandInvalidArgumentError` (not supported)
- **Non-CUA without `experimental: true`**: Throws
`ExperimentalNotConfiguredError`
### Example Usage
```typescript
const result = await agent.execute({
instruction: "search for a shampoo on amazon and click into one of the results",
maxSteps: 20,
output: z.object({
productName: z.string().describe("The name of the shampoo product"),
price: z.string().describe("The price of the product"),
rating: z.string().describe("The star rating of the product"),
}),
});
console.log(result.output);
// { productName: "...", price: "$12.99", rating: "4.5 out of 5 stars" }
```
# Test Plan
- [x] Verify close tool is called when agent naturally completes (no
change in behavior)
- [x] Verify close tool is forced when `maxSteps` is reached
- [x] Verify `output` schema extracts data correctly in `execute()` mode
- [x] Verify `output` schema extracts data correctly in `stream()` mode
- [x] Verify `output` throws `StagehandInvalidArgumentError` when used
with CUA mode
- [x] Verify `output` throws `ExperimentalNotConfiguredError` when used
without `experimental: true`
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Ensures every agent run ends with a structured final response and adds
optional structured output via a Zod schema. Improves reliability by
always setting completion status and final reasoning.
- **New Features**
- Always triggers a "close" tool call at the end of a run (LLM stops or
maxSteps), for both execute() and stream().
- Optional output schema: pass output: z.object({...}) to return typed
data in result.output.
- Validation: output schema is not supported in CUA (throws
StagehandInvalidArgumentError). In non-CUA, requires experimental: true
(throws ExperimentalNotConfiguredError otherwise).
- Removed "close" from the main tool list and system prompt; closing is
handled automatically post-run.
<sup>Written for commit dfb703a.
Summary will update on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
---------
Co-authored-by: Nick Sweeting <github@sweeting.me>1 parent 425138b commit 6fbf5fc
11 files changed
Lines changed: 273 additions & 52 deletions
File tree
- .changeset
- packages/core
- lib/v3
- agent
- prompts
- tools
- utils
- handlers
- tests
- types/public
- tests/public-api
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
71 | 70 | | |
72 | 71 | | |
73 | 72 | | |
| |||
92 | 91 | | |
93 | 92 | | |
94 | 93 | | |
95 | | - | |
96 | 94 | | |
97 | 95 | | |
98 | 96 | | |
| |||
224 | 222 | | |
225 | 223 | | |
226 | 224 | | |
227 | | - | |
228 | | - | |
229 | 225 | | |
230 | 226 | | |
231 | 227 | | |
| |||
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | 6 | | |
8 | 7 | | |
9 | 8 | | |
| |||
87 | 86 | | |
88 | 87 | | |
89 | 88 | | |
90 | | - | |
| 89 | + | |
91 | 90 | | |
92 | 91 | | |
93 | 92 | | |
| |||
121 | 120 | | |
122 | 121 | | |
123 | 122 | | |
124 | | - | |
125 | 123 | | |
126 | 124 | | |
127 | 125 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
Lines changed: 8 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
59 | 62 | | |
60 | 63 | | |
61 | 64 | | |
| |||
97 | 100 | | |
98 | 101 | | |
99 | 102 | | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
100 | 106 | | |
101 | 107 | | |
102 | 108 | | |
| |||
0 commit comments