Build an OpenAI Chatbot in Python With Persistent Context
Setting up an OpenAI chatbot in Python takes a few lines of code. Keeping conversation state across sessions and giving the bot project rules and current progress is the harder part. Here is how to do both.
Updated 4 min read
An OpenAI chatbot in Python sends a list of messages to the API, reads the reply and appends it to the list before the next call. That messages list is the conversation state: without it, each API call is an independent question rather than a turn in a continuing exchange.
For context that spans more than one chat session, the list needs to persist somewhere outside the script. Tools like fenbs let a connected assistant read project rules and Where we left off at the start of a session, so the bot can continue from an agreed record rather than starting fresh each time.
What you need before you start
- An OpenAI account with API access and an API key.
- Python 3.9 or later, installed locally or available in a Google Colab notebook.
- The openai package: run
pip install openaiin your terminal or notebook.
Set your API key as an environment variable (OPENAI_API_KEY) rather than pasting it directly into the script. On macOS and Linux, add export OPENAI_API_KEY=your_key to your shell profile. On Windows, add it through the environment variables panel in system settings.
Setting up the basic conversation loop
The core loop initializes a messages list with a system message, adds each user turn, calls the API with the full list and appends the reply. The system message gives the bot its standing instructions for the session.
import os
from openai import OpenAI
client = OpenAI()
messages = [{"role": "system", "content": "You are a helpful assistant."}]
while True:
user_input = input("You: ")
if user_input.lower() in ("exit", "quit"):
break
messages.append({"role": "user", "content": user_input})
response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
reply = response.choices[0].message.content
messages.append({"role": "assistant", "content": reply})
print(f"Bot: {reply}")Keep the system message specific. For a project-focused bot, include the scope: what it should help with, what it must not change, and any conventions it is expected to follow. A vague system message produces inconsistent behavior as the conversation grows longer.
Saving and reloading conversation history
The messages list above disappears when the script exits. To continue a conversation across sessions, write the list to a file after each turn and reload it on startup.
import json
def load_history(path="history.json"):
if os.path.exists(path):
with open(path) as f:
return json.load(f)
return [{"role": "system", "content": "You are a helpful assistant."}]
def save_history(messages, path="history.json"):
with open(path, "w") as f:
json.dump(messages, f)A long messages list increases token usage on every call. Trim older turns beyond a practical limit, or summarize earlier parts of the conversation before appending the summary. For production use, a database is safer than a local JSON file and easier to query when something goes wrong.
Adding tool calls to extend what the bot can do
Tool calls let the chatbot take actions or read data during a conversation. You define each tool as a JSON schema object and pass the list to the API call. When the model returns a tool call instead of a direct reply, you run the matching function locally and send the result back as a new message.
The OpenAI Agents SDK provides a higher-level abstraction for chatbots that need many tools or multi-step workflows. For a simple bot with one or two actions, the plain tool-calling API is usually enough and easier to trace when something goes wrong. The OpenAI agent builder covers a no-code path to similar results.
Managing conversation length and token costs
The messages list grows every turn, and the entire list is sent to the API on each call. For a short session this is fine. For a long task or a bot that stays active across hours, a growing list adds to your token costs and will eventually hit the model's context window limit.
A practical approach is to summarize after every ten or twenty turns. Ask the model to compress what has been agreed and what remains, then replace the older turns with that summary. Keep the system message and the most recent turns in full; replace the middle with a compact record of earlier decisions. This preserves the useful context without sending the full transcript on every call.
Running the chatbot in Google Colab
Colab is a practical environment for trying this setup without a local Python installation. Install the package with !pip install openai, store your API key in Colab Secrets under the key icon in the left panel, and read it with os.environ.get("OPENAI_API_KEY").
The input() function does not work inside Colab notebook cells. Use an ipywidgets text field or hardcode a test message to exercise the loop. The rest of the code works unchanged. For connecting a Python environment to an MCP server, the MCP server in Python guide covers the setup. For building a Python chatbot for business deployment, see AI chatbot for business.
Give your bot a project record to start from
Connect fenbs over MCP and ask your chatbot to read project rules and Where we left off at the start of each session. Decisions and rules appear first in the AI context, so the bot starts from what is already settled. fenbs does not import chat history or read your Python scripts; it holds the rules, tasks and progress you put there. Create a free account and add the first rules your bot should always follow.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
How to do this with fenbs
The setup links project context to each new session.
- Create a free account at fenbs.ai and add a project for the work the chatbot supports.
- Write project rules as Decisions and rules. Mark recurring instructions as standing rules so they appear first when a connected assistant reads the AI context.
- Add current tasks and update Where we left off whenever significant progress is made.
- Connect from Integrations using the MCP setup guide for your AI coding tool.
- At the start of each session, include a system message instructing the bot to read the project context, including its rules and Where we left off, before it responds to the first user message.
fenbs does not currently offer a Python library for direct API calls from a script. Connection to fenbs goes through an AI app that supports MCP. If your chatbot runs inside Claude Code, Cursor or another supported tool, that tool handles the fenbs connection on your behalf.