Welcome to the first lesson in your journey to mastering the Model Context Protocol (MCP) and its use with the OpenAI Agents SDK in Python. MCP is an open standard designed to enable large language models (LLMs) to securely and efficiently connect with external applications, tools, and data sources through a unified protocol. By providing a standardized way for AI models to access and interact with real-time information, MCP makes it possible to build more capable, context-aware agents that can perform complex tasks and integrate seamlessly with a wide range of systems.
Before we dive into MCP and tool integration, it’s important to first build a solid foundation in how agents work using the OpenAI Agents SDK. In this lesson, you will learn how to create a simple agent and understand the basics of agent execution. This foundational knowledge will prepare you for more advanced topics in future lessons, including developing and integrating your own MCP server. Get ready to take your first step toward building intelligent, tool-empowered agents!
The OpenAI Agents SDK is a Python library that makes it easy to build, manage, and run AI agents powered by large language models. With this SDK, you can create agents that reason, use tools, interact with other agents, and perform complex tasks in a structured way. Its simple and flexible design lets you quickly prototype and deploy agentic applications. For more details, you can check out the OpenAI Agents SDK Documentation.
If you’re working in your own local environment, you’ll need to install the library and set your OpenAI API key before you can start building agents. To install the SDK, you can use pip:
After installing, set your OpenAI API key as an environment variable. The command you use depends on your operating system:
While using the CodeSignal coding environment in this course, you don’t need to worry about installation or API keys—everything is already set up for you. You can jump right in and start running the code examples as you learn.
A key feature of the OpenAI Agents SDK is the agent loop. This loop is what sets an agent apart from a simple chat model.
A simple chat model, like GPT-4 in a basic chat interface, takes your input and generates a single response—there’s no memory of previous steps, no ability to call tools, and no way to interact with other systems. It’s a one-shot exchange: you ask a question, and the model answers.
An agent, on the other hand, can perform much more complex tasks thanks to the agent loop. Here’s how the agent loop works and why it’s different:
- Input Reception: The agent receives an input (such as a user query).
- Reasoning and Planning: The agent uses the language model (LLM) to decide what to do next. This could be generating a direct answer, calling an external tool, or handing off the task to another agent.
- Action Execution:
- If the agent needs to use a tool (like a calculator, web search, or database), the loop executes the tool call, collects the result, and feeds it back into the agent.
- If the agent needs to delegate, the loop can pass control to another agent.
- Iterative Processing: The agent loop repeats this process—reasoning, acting, and updating—until a final answer is produced or a maximum number of steps is reached.
- Final Output: Once the agent determines it has enough information, it produces a final output and the loop ends.
This iterative, multi-step process allows agents to break down complex problems, use external resources, and coordinate with other agents—all automatically managed by the SDK. The agent loop is what enables agents to go beyond simple Q&A and handle real-world tasks that require reasoning, tool use, and multi-step workflows.
Now that you understand the agent loop and how agents differ from simple chat models, let’s see how to put this into practice by creating a basic agent. Here is an example of how to create a simple agent to provide creative, healthy recipes:
In the OpenAI Agents SDK, you define an agent by providing the following parameters:
- name: A label to identify your agent (e.g., "Recipe Chef").
- instructions: Guidance that shapes the agent’s behavior and responses (for example, asking the agent to provide clear steps and healthy ingredients).
- model (optional): Specifies which language model the agent will use to generate answers. For example,
"gpt-4.1"
is a cost-effective model optimized for agentic workflows. It offers strong performance, a large context window and great instruction following. If you do not specify a model, the SDK will use a default model for the agent.
By clearly defining these parameters, you ensure your agent behaves as intended and leverages the right language model for your specific use case. This flexibility allows you to tailor agents for a wide range of applications and performance needs.
After creating an agent, you need to run it with a specific input to perform a task. This is accomplished using the Runner
class, which provides methods to execute agents in different modes:
-
Asynchronous Execution (
Runner.run
): Executes the agent asynchronously, allowing the program to perform other tasks concurrently. This method is recommended for most applications, especially when the agent interacts with external tools, as it prevents blocking the main program flow. -
Synchronous Execution (
Runner.run_sync
): Executes the agent synchronously, blocking the program until the agent completes its task. This method wraps the asynchronousrun
method and may not function properly in environments that already have an event loop, such as within asynchronous functions or frameworks like FastAPI. -
Streaming Execution (
Runner.run_streamed
): Executes the agent in streaming mode, returning aRunResultStreaming
object that allows real-time processing and delivery of the agent's outputs. This is useful for applications requiring immediate feedback or progress updates.
Understanding these execution modes allows you to tailor the agent's behavior to best fit your application's requirements.
In the OpenAI Agents SDK, synchronous execution uses the Runner.run_sync
method. This mode processes the agent’s input and returns the output in a blocking manner, meaning your program waits for the agent to finish before moving on. Synchronous execution is straightforward and works well for simple, sequential tasks where concurrent processing is not needed.
Here is how you can run your agent synchronously:
In this example, the Runner.run_sync
method is called with two parameters:
starting_agent
specifies the agent you want to run.input
is the prompt or question you want the agent to answer.
The method returns a result object after the agent finishes processing. You can extract the agent's final response from this object using the final_output attribute, which contains the complete answer generated by the agent. The program blocks until the agent completes processing, and then the final output is printed.
When run with the input "Give me a quick recipe for a healthy smoothie", the agent might produce output like this:
Asynchronous execution uses the Runner.run
method and allows your program to continue running other tasks while waiting for the agent's response. This is especially important when your agent interacts with external tools, as these operations can take time and may involve network or API calls. By using Python's async
and await
syntax, your application remains responsive and can efficiently handle multiple tasks at once.
Here is an example of running your agent asynchronously:
In this snippet, we need to define an asynchronous function (async def main()
) because the Runner.run
method itself is asynchronous. Asynchronous functions in Python can use the await
keyword to pause execution until an asynchronous operation completes, without blocking the entire program.
The asyncio.run(main())
line is crucial because it creates and manages the event loop required to execute asynchronous code. The event loop is what allows Python to handle multiple operations concurrently - it keeps track of all running asynchronous tasks and switches between them efficiently. Without this event loop management, asynchronous functions cannot execute properly.
This approach is recommended for most real-world applications, especially those that require integration with other services or need to handle multiple requests concurrently. For example, if your agent needs to call external APIs, query databases, or process multiple user requests simultaneously, asynchronous execution prevents your application from freezing while waiting for these operations to complete.
Streaming execution uses the Runner.run_streamed
method to provide real-time processing and delivery of the agent’s outputs. Instead of waiting for the full response, the agent streams partial results as they become available. This is useful for applications that require immediate feedback or progress updates, such as live chat interfaces or interactive tools.
Here is how to use streaming execution:
In this example, the Runner.run_streamed
method is called with your agent and the input query. An asynchronous loop processes each streaming event as it arrives, allowing you to handle partial outputs or progress updates in real time.
When you run this code, you'll see a series of events being streamed as the agent processes the request. Here's a sample of what these events might look like:
As you can see, the streaming output provides detailed information about each step of the agent's processing, including initialization events and the final response. While this detailed stream is useful for monitoring the agent's progress or building responsive UIs, you might still want just the final answer. Even when using streaming mode, you can access the complete final output after streaming completes by using result.final_output
, just as you would with synchronous or asynchronous execution. This gives you the flexibility to both monitor the process in real-time and easily extract the final result when needed.
In this lesson, you built a solid foundation for working with the OpenAI Agents SDK in Python. You learned how agents differ from simple chat models by exploring the agent loop—a process that allows agents to reason, plan, and act in multiple steps. You saw how to create a basic agent by providing a name, clear instructions, and a model, and then discovered three different ways to run your agent: synchronously, asynchronously, and with streaming.
With these fundamentals in place, you’re ready to move on to more advanced topics, where you’ll get hands-on practice applying what you’ve learned and start extending your agents’ capabilities. Dive into the practice exercises ahead—they’re designed to help you solidify your understanding and gain confidence with the OpenAI Agents SDK.
