If you're asking how to build an AI agent with ChatGPT, there are two honest answers, and picking the wrong one wastes a week. The no-code path builds the agent inside ChatGPT — a Custom GPT for a simple configured assistant, or a Workspace Agent (OpenAI's newer, autonomous successor to Custom GPTs) for something that runs on its own. The code path builds the agent inside your own product with the OpenAI Agents SDK — you define the agent, give it tools, and run the loop. The deciding question isn't your skill level; it's where the agent has to live.

Here's the whole decision in one screen:

The rest of this guide takes each path far enough to act on, gives you a working Python agent you can run today, and ends with the cost math so the loop doesn't surprise you on the bill.

The no-code path: build the agent inside ChatGPT#

If the agent will live inside ChatGPT and a non-engineer will run it, you may not need to write anything.

A Custom GPT is the fastest start: ChatGPT configured with your instructions, some uploaded knowledge files, and optional Actions (calls to an external API via an OpenAPI schema). It's genuinely useful for a focused assistant — a support triager, a style-guide checker, a doc Q&A bot. Its limit is structural: a Custom GPT answers one turn at a time and doesn't own a real loop, so it can't reliably chew through a multi-step task on its own. One practical note for 2026: which plans can create new Custom GPTs has been in flux, so check what your tier allows before you build around it.

A Workspace Agent is the more capable no-code option, and OpenAI positions it as the ChatGPT-native successor to Custom GPTs. The difference that matters is autonomy and persistence: a Workspace Agent can run in the background, keep going after you close the browser, use multiple tools across a task, and follow schedules — with memory and governance built in. That's much closer to what people mean by "agent." If the job is "watch this inbox and draft replies" or "every morning summarize these dashboards," a Workspace Agent does it without code.

When to graduate to code: the moment the agent has to live inside your product, expose your UX, run your tool logic, or control where data is stored and how approvals work. No-code stops where your own runtime begins.

The code path: the OpenAI Agents SDK#

For a real, embeddable agent, the most direct route on OpenAI is the Agents SDK — an open-source Python (and TypeScript) framework, openai-agents, at v0.22.x as of September 2026. It gives you the six primitives every agent needs, documented in the SDK's own repo:

It's also provider-agnostic: the same code can route to 100+ models via LiteLLM, so choosing the SDK doesn't weld you to OpenAI. The default model is gpt-5.6-luna (a cheap tier, since v0.20.0), and you can override it per-run.

A working agent in ~20 lines

Install the SDK, set your key, and this is a complete tool-using agent — one custom function tool plus OpenAI's hosted web search:

# pip install openai-agents        (0.22.x as of Sept 2026)
# export OPENAI_API_KEY=sk-...
import asyncio
from agents import Agent, Runner, WebSearchTool
from agents.decorators import tool   # current docs use @tool;
                                     # older tutorials show: from agents import function_tool

@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city.

    Args:
        city: The city to look up.
    """
    # a real tool would call a weather API here
    return f"It's sunny in {city}."

agent = Agent(
    name="Assistant",
    instructions="You are a concise assistant. Use tools when they help.",
    model="gpt-5.6-luna",          # SDK default since v0.20.0; override per run if needed
    tools=[get_weather, WebSearchTool()],
)

async def main():
    result = await Runner.run(agent, "What's the weather in Lisbon, and any news there today?")
    print(result.final_output)

if __name__ == "__main__":
    asyncio.run(main())

Runner.run executes the whole loop — the model decides when to call get_weather or search the web, reads the results, and keeps going until it has a final answer. (Runner.run_sync(agent, "...") is the blocking variant if you're not in async code.) A note on the decorator: current docs lead with @tool from agents.decorators, while plenty of older tutorials still use the @function_tool alias — both work, so don't be thrown when you see the other one.

From here you add the pieces you need: OpenAI's hosted toolsWebSearchTool, FileSearchTool (over your Vector Stores), CodeInterpreterTool (sandboxed code), HostedMCPTool (a remote MCP server) — plus Handoffs to specialist agents and Guardrails to validate inputs and outputs. If you're deciding whether a capability belongs as a function tool, a hosted tool, or an MCP server, our guide to agent skill vs. MCP server frames that call.

The three API surfaces underneath (and which to use)#

The SDK is built on OpenAI's API, and it helps to know the layers, because "how do I build an agent" often really means "which API do I call":

The clean mental model: Workspace Agents (no code) → Agents API (OpenAI runs the loop) → Agents SDK (you run the loop, your infra) → Responses API (the rawest primitive). We took the managed-vs-self-run trade apart in who runs your agent loop; the short version is that the managed API buys velocity at the cost of holding your session state, so keep your prompts and tools portable behind a gateway either way.

What it costs — and how to keep it down#

Agents are token-hungry: the loop re-sends context on every step, and each tool call adds its own round trip. Two levers do most of the cost control. First, run the loop on a cheap model — the SDK already defaults to gpt-5.6-luna for exactly this reason — and reserve a stronger model for the genuinely hard steps via a router. Second, use prompt caching so the large, unchanging head of your prompt (system instructions, tool definitions) bills at a fraction of the base rate on repeat calls.

Because model prices move monthly, don't trust a hard-coded estimate. Put your real numbers — requests per month, tokens per step, how many steps a task takes — into our LLM API pricing calculator and price the workload before you scale it. Then meter cost per successful task, not per token, so a chatty agent that needs three retries shows its true cost.

The one rule under both paths#

Whether you build no-code or in code, the durable move is the same: keep it swappable. On the no-code side, that means not welding a business process to a single vendor's hosted workflow you can't export. On the code side, it means putting your prompts, tools, and state behind a thin gateway so you can change the model — or the framework — without a rewrite. Start on whichever path matches where your agent lives, ship the smallest version that does one real job, and let the loop earn its next tool before you add it.