Can't add messages to thread while a run is active

Hi all. I’m following this tutorial by @ joyasree78 and have tried to make a few changes of my own. When I run the code and ask the first question, I’m getting this error:
raise self._make_status_error_from_response(err.response) from None openai.BadRequestError: Error code: 400 - {'error': {'message': "Can't add messages to thread_Xhtc7rjp5KYTKxWdfnDuLD6U while a run run_rF3R9B6ZqrJmGUhjYNoNb93E is active.", 'type': 'invalid_request_error', 'param': None, 'code': None}}

Thanks

Here’s my code:

import os
from openai import OpenAI, AsyncOpenAI
from dotenv import load_dotenv
import asyncio

# env variables
load_dotenv()
my_key = os.getenv('OPENAI_API_KEY')

# OpenAI API
client = AsyncOpenAI(api_key=my_key)


async def deploy_assistant():
    # Create the assistant
    assistant = await client.beta.assistants.create(
        name="Coding Buddy",
        instructions="You are a programming support chatbot. Use your knowledge of programming languages to best respond to user queries.",
        model="gpt-4-1106-preview",
        tools=[{"type": "code_interpreter"}],
        #file_ids=[file.id]
    )
    return assistant


async def run_assistant(assistant_id,thread):

    run =  await client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant_id
    )

    runInfo = await client.beta.threads.runs.retrieve(
        thread_id=thread.id,
        run_id=run.id
    )

    return run, runInfo


async def get_answer(run, runInfo, thread, user_question):
    print("Looking for an answer to your question...")
    # add a message to a thread
    message = await client.beta.threads.messages.create(
        thread_id=thread.id,
        role="user",
        content= user_question
    )
    
    while runInfo.status != "completed":
        runInfo =  await client.beta.threads.runs.retrieve(
            thread_id=thread.id,
            run_id=run.id
        )

    print("All done...")
    # Get the messages from the thread
    messages = await client.beta.threads.messages.list(message.thread_id)
    message_content = await messages.data[0].content[0].text.value
    return message_content


if __name__ == "__main__":
    async def main():
        # assistant = await deploy_assistant()
        # print(assistant)
        thread = await client.beta.threads.create()
        print("Thread created is: ", thread.id)
        while True:
            question = input("How may I help you today? \n")
            if "exit" in question.lower():
                break
            
            run,runInfo = await run_assistant("asst_3GtOWcJBMrBs4EiUjP9ZXY9P",thread)
            message_content = await get_answer(run, runInfo, thread, question)
            print("FYI, your thread is: ", thread.id)
            print(message_content)
        print("Thanks and happy to serve you")
    asyncio.run(main())
2 Likes

the function get_answer is creating the message before checking status, I don’t think the beta supports subscriptions yet, so the async likely returns a status of “in-progress” once. For now a loop works, on each loop retrieve the runInfo, with a little sleep, and only when the status is equal to complete create new message this is what worked for me

2 Likes

Can you write the updated function please. I am facing the same error.

Thanks.

After a bit of research online, this works for me.

import os
from openai import OpenAI, AsyncOpenAI
from dotenv import load_dotenv
import asyncio
import time

# env variables
load_dotenv()
my_key = os.getenv('OPENAI_API_KEY')

# OpenAI API
client = AsyncOpenAI(api_key=my_key)


async def create_assistant():
    # Create the assistant
    assistant = await client.beta.assistants.create(
        name="Coding MateTest",
        instructions="You are a programming support chatbot. Use your knowledge of programming languages to best respond to user queries.",
        model="gpt-4-1106-preview",
        tools=[{"type": "code_interpreter"}],
        #file_ids=[file.id]
    )

    return assistant


async def add_message_to_thread(thread_id, user_question):
    # Create a message inside the thread
    message = await client.beta.threads.messages.create(
        thread_id=thread_id,
        role="user",
        content= user_question
    )
    return message


async def get_answer(assistant_id, thread):
    print("Thinking...")
    # run assistant
    print("Running assistant...")
    run =  await client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant_id
    )

    # wait for the run to complete
    while True:
        runInfo = await client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
        if runInfo.completed_at:
            # elapsed = runInfo.completed_at - runInfo.created_at
            # elapsed = time.strftime("%H:%M:%S", time.gmtime(elapsed))
            print(f"Run completed")
            break
        print("Waiting 1sec...")
        time.sleep(1)

    print("All done...")
    # Get messages from the thread
    messages = await client.beta.threads.messages.list(thread.id)
    message_content = messages.data[0].content[0].text.value
    return message_content


if __name__ == "__main__":
    async def main():
        # Colour to print
        class bcolors:
            HEADER = '\033[95m'
            OKBLUE = '\033[94m'
            OKCYAN = '\033[96m'
            OKGREEN = '\033[92m'
            WARNING = '\033[93m'
            FAIL = '\033[91m'
            ENDC = '\033[0m'
            BOLD = '\033[1m'
            UNDERLINE = '\033[4m'
    
        # Create assistant and thread before entering the loop
        assistant = await create_assistant()
        print("Created assistant with id:" , f"{bcolors.HEADER}{assistant.id}{bcolors.ENDC}")
        thread = await client.beta.threads.create()
        print("Created thread with id:" , f"{bcolors.HEADER}{thread.id}{bcolors.ENDC}")
        while True:
            question = input("How may I help you today? \n")
            if "exit" in question.lower():
                break
            
            # Add message to thread
            await add_message_to_thread(thread.id, question)
            message_content = await get_answer(assistant.id, thread)
            print(f"FYI, your thread is: , {bcolors.HEADER}{thread.id}{bcolors.ENDC}")
            print(f"FYI, your assistant is: , {bcolors.HEADER}{assistant.id}{bcolors.ENDC}")
            print(message_content)
        print(f"{bcolors.OKGREEN}Thanks and happy to serve you{bcolors.ENDC}")
    asyncio.run(main())

Hope that helps :blush:

2 Likes

I think that the correct way is this:

putting the run after the message. thanks a lot.

const message = await openai.beta.threads.messages.create(thread.id, {
        role: 'user',
        content: userMessage,
    });

    const run = await openai.beta.threads.runs.create(thread.id, {
        assistant_id: assistant.id,
    });