Skip to content
Open
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
18 changes: 13 additions & 5 deletions helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -590,14 +590,20 @@ The underlying `AbortController` for the runner.
#### Abort on a function call

If you have a function call flow which you intend to _end_ with a certain function call, then you can use the second
argument `runner` given to the function to either mutate `runner.messages` or call `runner.abort()`.
argument `runner` given to the function to inspect the terminating call, mutate `runner.messages`, or call
`runner.abort()`.

Because `abort()` ends the run immediately, the `final*` helpers will reject afterwards. Capture the terminating call
inside the function itself (or via event handlers), then await `runner.done()` and handle the abort error.

```ts
import OpenAI from 'openai';

const client = new OpenAI();

async function main() {
let terminatingCall: unknown;

const runner = client.chat.completions
.runTools({
model: 'gpt-3.5-turbo',
Expand All @@ -607,17 +613,19 @@ async function main() {
type: 'function',
function: {
function: function updateDatabase(props, runner) {
runner.abort()
terminatingCall = props;
runner.abort();
},
Comment on lines 615 to 618
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this example terminatingCall is assigned props, which are the tool/function arguments, not the full function/tool call (name/id/raw arguments). The variable name and log message (“Function call that ended the run”) are misleading; consider renaming to reflect that it’s arguments, or capture the actual tool call object via the appropriate event and log that instead.

Copilot uses AI. Check for mistakes.
}
},
],
})
.on('message', (message) => console.log(message));
.on('message', (message) => console.log(message))
.on('abort', (error) => console.log('Run aborted:', error.message));

const finalFunctionCall = await runner.finalFunctionCall();
console.log('Final function call:', finalFunctionCall);
await runner.done().catch(() => {});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle only abort errors in done() catch

This line suppresses all failures from runner.done(), not just the expected APIUserAbortError from runner.abort(). In the example, network/auth/API errors would be silently ignored and execution would continue as if the run ended normally, which can mislead users copying this pattern. Catching and filtering only abort errors (and rethrowing others) would keep the abort example accurate without hiding real failures.

Useful? React with 👍 / 👎.

Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await runner.done().catch(() => {}); swallows all errors (network/API errors, parsing errors, etc.), not just the expected abort. This can lead readers to silently ignore failures. Catch the error and only ignore APIUserAbortError (or check error.name === 'APIUserAbortError'), and rethrow anything else.

Suggested change
await runner.done().catch(() => {});
try {
await runner.done();
} catch (error) {
if ((error as { name?: string })?.name !== 'APIUserAbortError') {
throw error;
}
}

Copilot uses AI. Check for mistakes.
console.log('Function call that ended the run:', terminatingCall);
}

main();
Expand Down
Loading