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
19 changes: 19 additions & 0 deletions .changeset/warm-lions-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
'@openrouter/agent': patch
---

Relax an unchanged forced `toolChoice` (`required`, a specific tool, or `allowed_tools` with `mode: 'required'`) to `auto` after it produces a tool call, including follow-ups resumed after approval, HITL, client-tool, or async-tool pauses. Dynamically resolved choices re-arm when their semantic value changes. This lets the model synthesize a final text answer instead of being forced to call tools until the step budget runs out (DEV-785).

```ts
const result = callModel(client, {
model: 'openai/gpt-4o',
input: 'Plan, research, then submit.',
tools: [planTool, searchTool, submitTool] as const,
toolChoice: ({ numberOfTurns }) =>
numberOfTurns === 0
? { type: 'function', name: 'plan' }
: numberOfTurns === 3
? { type: 'function', name: 'submit' }
: 'auto',
});
```
20 changes: 20 additions & 0 deletions packages/agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,26 @@ const confirmTool = tool({
});
```

**Forced tool choices** are one-shot for each resolved semantic value. After a
forced choice produces a tool call, unchanged follow-up choices are relaxed to
`auto` so the model can either call another tool or answer in text. A dynamic
choice re-arms when it resolves to a different value (or after an unforced
turn):

```typescript
callModel(client, {
model: 'openai/gpt-4o',
input: 'Plan, research, then submit.',
tools: [planTool, searchTool, submitTool] as const,
toolChoice: ({ numberOfTurns }) =>
numberOfTurns === 0
? { type: 'function', name: 'plan' }
: numberOfTurns === 3
? { type: 'function', name: 'submit' }
: 'auto',
});
```

### Stop Conditions

Control when the agent loop stops executing tools:
Expand Down
Loading