Company OAsAll ProblemsOA CalendarInterview ExperiencesPremium
OAHelper

Built by students, for students - practice company-specific OAs, DSA sheets, and real interview experiences to land your dream role.

© 2026 OAHelper.in·Terms·Privacy·Refunds·Trust & Safety·Contact·
Ready to crack your next OA?

Practice company-specific questions trusted by thousands of students across India.

Start PracticingGo Premium
OA Practice·DSA·Placements

Disclaimer: OAHelper is an independent educational platform. We (oahelper.in) do not own the images or questions shown. Content is uploaded by users.

Module 03

OpenAI Agents SDK

  • LangGraph Stateful Graphs
  • AutoGen Actor Model
  • CrewAI Role-Based Crews
  • OpenAI Agents SDK
  • Claude Agent SDK
  • Agno and Mastra
On this page

This week

  • LangGraph Stateful Graphs
  • AutoGen Actor Model
  • CrewAI Role-Based Crews
  • OpenAI Agents SDK
  • Claude Agent SDK
  • Agno and Mastra

In plain words

Think of a college fest help desk. One person cannot answer registration, food coupons and refunds all at once, so the front desk sends you to the right counter. The OpenAI Agents SDK does the same for software: a triage agent hands the conversation to a specialist agent, guardrails check what comes in and what goes out, and tracing keeps a record of every step so you can see what happened.

How it flows

  1. 1User asks→
  2. 2Input guardrail→
  3. 3Triage agent→
  4. 4Handoff to specialist→
  5. 5Output guardrail→
  6. 6Reply

A tiny example

Python
triage = Agent("triage", handoffs=["billing"])

if not input_guardrail(text):
    stop("tripwire")
kind, value = think(triage, text)
if kind == "handoff":
    # model called transfer_to_billing
    agent = agents[value]
reply = run_tool(agent, text)

Notice the handoff is nothing special: the model just calls a tool named transfer_to_<agent>, and the runtime swaps in that agent.


What you will learn

  • What the OpenAI Agents SDK is, in five simple pieces.
  • How one agent passes work to another agent (a "handoff").
  • How guardrails stop bad input and bad output.
  • How tracing lets you see what your agent actually did.

The problem, simply

Think of a college fest help desk. One table, one volunteer, and every question comes to him: registration, food coupons, stage timings, a ₹200 refund, a lost ID card.

Now think how a real fest works. There is a front desk. You tell your problem, and they say "accounts counter, second floor". Each counter knows only its own job, and knows it well.

Software agents have the same problem. When you put every instruction into one prompt — refunds, technical support, sales, escalation — the prompt becomes huge and the model starts mixing things up. It answers a refund question with a sales pitch.

Also, nobody is checking the door. A user can paste something nasty, or the agent can leak somebody's phone number. And when it breaks at 2 AM, you have no idea what happened inside.

The OpenAI Agents SDK is a small Python library that solves exactly these three things: splitting work, checking the door, and keeping a record.

The idea

The five pieces

The whole SDK is built from five things. Remember these five names — interviewers love asking this.

  1. Agent — a model plus instructions plus its tools. One counter at the help desk.
  2. Handoff — one agent passing the conversation to another agent.
  3. Guardrail — a check that says yes or no, on input, on output, or on a tool call.
  4. Session — conversation history that is saved automatically between turns.
  5. Tracing — a built-in record of every model call, tool call, handoff and guardrail.
  1. 1User message→
  2. 2Input guardrail→
  3. 3Triage agent→
  4. 4Handoff→
  5. 5Billing agent→
  6. 6Output guardrail→
  7. 7Reply

A handoff is just a tool

Here is the trick.

The model does not learn any new ability to delegate. The SDK simply adds a tool to its tool list, named transfer_to_billing_agent. From the model's side it looks exactly like get_weather. It just calls it.

When the model calls that tool, the runtime does three things: it carries the conversation over, it starts the billing agent with the billing agent's own instructions, and the run continues from there. Same conversation, new expert.

IMP

Note: The tool name always follows the shape transfer_to_<agent_name>. If somebody in an interview asks "how does the model see a handoff", this is the answer.

Suppose Priya types "I paid ₹499 for premium but it still shows free". The triage agent sees a money matter and calls transfer_to_billing_agent. The billing agent takes over, with instructions that only talk about payments. Priya never sees the transfer; she just gets a correct answer.

Guardrails: three places to check

A guardrail is a small check. The SDK gives you three kinds, and the difference is where they run.

  • Input guardrail — runs on the very first agent, on what the user sent. Use it to reject abuse or off-topic requests before you spend a single rupee on model tokens.
  • Output guardrail — runs on the last agent, on what you are about to send back. Use it to catch leaked personal details or policy violations.
  • Tool guardrail — runs per function tool. Check the arguments, check permissions, log the call.

When a guardrail says no, we say the tripwire was triggered, and the run stops with an error instead of returning a bad answer.

There is also a timing choice. In parallel mode (the default), the guardrail check runs at the same time as the main model call. The user waits less. But if the guardrail trips, the main model's work is thrown away, so those tokens are wasted. In blocking mode, the guardrail runs first and the main call happens only if it passes. No wasted tokens, but the user waits a bit longer.

IMPRemember: parallel = faster but wastes tokens when it trips; blocking = slower but never wastes tokens.

Sessions and tracing

A Session stores the chat history somewhere — SQLite, Redis, whatever you like — and loads it back next turn. You stop passing history around by hand.

Tracing is on by default. Every model call, tool call, handoff and guardrail produces a span, which is basically one timed entry in a tree. If you do not want it, set the environment variable OPENAI_AGENTS_DISABLE_TRACING=1. You can also attach your own processor to send the same spans to your own logging backend.

  1. 1Span: run→
  2. 2Span: LLM call→
  3. 3Span: tool call→
  4. 4Span: handoff→
  5. 5Span: guardrail
Warning

Warning: Spans can quietly capture the actual message content. If your agent handles PAN numbers or medical details, store the content somewhere else and keep only an ID in the span.

Build it

This is a toy version of the SDK in plain Python. No API key, no internet. The "model" is a fake function that decides things with simple rules, so you can watch the machinery.

Python
"""A tiny stand-in for the Agents SDK: agents, handoffs, guardrails, tracing."""

SPANS = []  # our whole trace lives here

def span(kind, name, detail=""):
    SPANS.append((kind, name, detail))

class Agent:
    def __init__(self, name, job, handoffs=()):
        self.name = name
        self.job = job
        self.handoffs = list(handoffs)  # names it may transfer to

def fake_model(agent, text):
    """Pretends to be an LLM. Returns ('handoff', target) or ('final', reply)."""
    span("llm", agent.name, text[:30])
    low = text.lower()
    for target in agent.handoffs:
        # the model 'calls' the tool transfer_to_<target>
        if target == "billing" and ("paid" in low or "refund" in low):
            return ("handoff", "billing")
        if target == "support" and ("error" in low or "crash" in low):
            return ("handoff", "support")
    return ("final", f"[{agent.name}] handled: {text}")

def input_guardrail(text):
    span("guardrail", "input")
    return "password" not in text.lower()   # tripwire on secrets

def output_guardrail(text):
    span("guardrail", "output")
    return "@" not in text                  # tripwire on leaked email

def run(agents, start, text, max_hops=3):
    if not input_guardrail(text):
        return "BLOCKED: input guardrail tripped"
    agent, hops = agents[start], 0
    while True:
        kind, value = fake_model(agent, text)
        if kind == "final":
            if not output_guardrail(value):
                return "BLOCKED: output guardrail tripped"
            return value
        hops += 1
        if hops > max_hops:                 # stops handoff drift
            return "BLOCKED: too many handoffs"
        span("handoff", f"transfer_to_{value}")
        agent = agents[value]

AGENTS = {
    "triage": Agent("triage", "route the user", handoffs=["billing", "support"]),
    "billing": Agent("billing", "payments only"),
    "support": Agent("support", "bugs only"),
}

for msg in ["I paid 499 but still free", "the app gives an error", "my password is abcd"]:
    SPANS.clear()
    print(run(AGENTS, "triage", msg))
    print("  trace:", " | ".join(f"{k}:{n}" for k, n, _ in SPANS))

Look at the trace line under each answer. For the first two messages you will see an llm span, then a handoff span, then a second llm span from the new agent — that is delegation happening. For the third message the run stops after the input guardrail span, so no model call happens at all. That is blocking mode saving you tokens.

Where you will see this

  • Customer-support bots on e-commerce sites, where a front agent routes you to orders, refunds or returns.
  • Coding assistants like Claude Code and Cursor, which run sub-agents for search, editing and testing.
  • Food delivery assistants that pass you from "where is my order" to a live-agent escalation flow.
  • Any company chatbot that must never say certain things — that "never say" list is an output guardrail.
  • Internal dashboards where the team replays a failed agent run span by span to find the bad step.

Common mistakes

  • Handoff drift. Agent A transfers to B, B transfers back to A, forever. Your bill grows and the user gets nothing. Always keep a hop counter and stop after N transfers.
  • Thinking tool guardrails cover everything. They only fire on your own function tools. Built-in tools like a file reader or a web fetcher need a separate policy, otherwise there is a hole in your wall.
  • Only guarding the input. Bad output is the one that reaches the customer. Input and output checks are different jobs; do both.
  • Making every agent able to reach every other agent. Then routing becomes random. Give each agent a short, deliberate handoff list.
  • Logging full message content in spans. Very useful in development, very dangerous in production with real user data.

If they ask in an interview

Q: How does a handoff actually work in the OpenAI Agents SDK?

A: The runtime exposes each possible target agent as a tool named transfer_to_<agent_name>. The model just calls that tool like any other. The runtime then carries the conversation across and continues the run with the target agent's own instructions and tools.

Q: What are input, output and tool guardrails, and when would you block instead of running in parallel?

A: Input guardrails check the user's message on the first agent, output guardrails check the final reply on the last agent, and tool guardrails validate individual function tool calls. Parallel is the default and lowers latency, but wastes tokens whenever it trips. I would use blocking mode when trips are common or the main call is expensive.

Q: How would you debug a multi-agent run that gave a wrong answer?

A: Tracing is on by default, so I would read the span tree — model calls, tool calls, handoffs, guardrails, in order — and find where the run went to the wrong agent or a tool returned junk. If the content is sensitive, I would store it outside the span and keep only a reference ID.

Try these

  1. Add a fourth agent called escalation and let support hand off to it when the user says "still not working". Check the trace shows two hops.
  2. Set max_hops=1 and make two agents transfer to each other. Watch the hop counter save you.
  3. Turn the input guardrail into a parallel-style one: call the model first, then check, and print how much work you threw away.
  4. Write the spans out as one JSON line per span instead of a text trace. Decide which fields you would keep if the messages contained real user data.

Words, simply

WordMeaning in simple words
AgentA model with its own instructions and its own set of tools
HandoffOne agent passing the conversation to another agent
TripwireThe error raised when a guardrail rejects something
GuardrailA yes-or-no check on input, output, or a tool call
SessionSaved chat history, loaded back automatically each turn
SpanOne timed entry in the record of what the agent did
Blocking guardrailCheck runs first; slower, but no tokens wasted on a reject
Parallel guardrailCheck runs alongside; faster, but wasted tokens on a reject

Quick recap

  • Five pieces: Agent, Handoff, Guardrail, Session, Tracing — know these by name.
  • A handoff is not magic; it is a tool named transfer_to_<agent_name> that the model calls.
  • Guard the input, guard the output, count your hops, and keep the trace clean of private data.

Check what you learned

1 / 7. What are the five building blocks of the OpenAI Agents SDK?
1/7
PreviousCrewAI Role-Based CrewsNextClaude Agent SDK

On this page