Possible to execute a callback on run end?

Hey there! I’m trying out the new assistant API and wondering if I’m missing something very basic - how do I trigger some action to get the thread contents on the end of a run automatically? I’ve set up my Assistant, and can create messages and runs. When I poll, eventually I get the updated thread. But I suspect there’s a more elegant way to do this than pulling every [n] milliseconds to look for an updated Thread object…

Apologies if this is elemental, I’m fairly new to this.

while run.status != "completed":
  run = client.beta.threads.runs.retrieve(

Could this be a good solution?

1 Like

@mehmet.koca thank you! In the end this is very close to what I wrote - wondering if there is a non-polling strategy for this :thinking:

But for the time being, this is working well and I’m unblocked. Cheers!

I’m also curious about a better solution :slight_smile:

+1 for callbacks on run complete instead of polling.

because it’s not just polling right? it’s polling followed by another call to thread messages to get the actual results. so its:

  • create and run thread (thank goodness these can be combined)
  • poll for run results
  • retrieve messages from the thread

a little bit rube goldberg, right?

Thanks for the feedback! We plan to improve this via streaming and webhooks for the Assistants API, but they are not quite ready in the beta right now. Working on it, and will share more as we ship these features.


Async typescript version:

export async function pollRunCompletion(thread_id: string, run_id: string) {
  let run_status;
  let isCompleted = false;

  // Polling interval in milliseconds
  const pollingInterval = 1000;

  // Poll the run status until it is completed
  while (!isCompleted) {
    try {
      run_status = await openai.beta.threads.runs.retrieve(thread_id, run_id);
      // console.log('Current run status:', run_status);

      // Check if the run is completed
      if (run_status.status === 'completed' || run_status.status === 'failed') {
        isCompleted = true;
      } else {
        // Wait for the specified interval before polling again
        await new Promise(resolve => setTimeout(resolve, pollingInterval));
    } catch (error) {
      console.error('Error polling run status:', error);
      throw error;

  // Once completed, retrieve the final messages from the thread
  const finalMessages = await openai.beta.threads.messages.list(thread_id);
  // console.log(finalMessages.data[0].content[0].text.value);
  // console.log('Final messages:', finalMessages.body.data);
  // console.log(finalMessages.body.data[0].content[0].text.value);

  // Return the final status and messages
  if (!run_status) {
    throw new Error("Run status is undefined");
  return {
    status: run_status.status,
    // messages: finalMessages.body.data[0].content[0].text.value
    messages: finalMessages.data[0].content[0].text.value

Hi @atty-openai! Any update on this? Thanks :slight_smile: