SPB Git

Repository Public

running-agents.md 8.0 KB 247 lines markdown

1# Running agents23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45Defining an agent is only the setup step. The runtime questions are what a single run does, how the next turn continues, and how the workflow behaves when it pauses for approvals or tool work.67## The agent loop89One SDK run is one application-level turn. The runner keeps looping until it reaches a real stopping point:10111. Call the current agent's model with the prepared input.122. Inspect the model output.133. If the model produced tool calls, execute them and continue.144. If the model handed off to another specialist, switch agents and continue.155. If the model produced a final answer with no more tool work, return a result.1617That loop is the core concept behind the SDK. Tools, handoffs, approvals, and streaming all build on top of it rather than replacing it.1819## Choose one conversation strategy2021There are four common ways to carry state into the next turn:2223| Strategy                                                                                                           | Where state lives         | Best for                                                               | What you pass on the next turn                 |24| ------------------------------------------------------------------------------------------------------------------ | ------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------- |25| `result.history` in TypeScript or `result.to_input_list()` in Python   | Your application          | Small chat loops and maximum control                                   | The replay-ready history                       |26| `session`                                                                                                          | Your storage plus the SDK | Persistent chat state, resumable runs, and storage you control         | The same session                               |27| `conversationId`                                                                                                   | OpenAI Conversations API  | Shared server-managed state across workers or services                 | The same conversation ID and only the new turn |28| `previousResponseId` in TypeScript or `previous_response_id` in Python | OpenAI Responses API      | The lightest server-managed continuation from one response to the next | The last response ID and only the new turn     |2930In most applications, pick one strategy per conversation. Mixing local replay with server-managed state can duplicate context unless you are deliberately reconciling both layers.3132Persist multi-turn state with sessions3334```javascript35import { Agent, MemorySession, run } from "@openai/agents";3637const agent = new Agent({38  name: "Tour guide",39  instructions: "Answer with compact travel facts.",40});4142const session = new MemorySession();4344const firstTurn = await run(agent, "What city is the Golden Gate Bridge in?", {45  session,46});47console.log(firstTurn.finalOutput);4849const secondTurn = await run(agent, "What state is it in?", { session });50console.log(secondTurn.finalOutput);51```5253```python54import asyncio5556from agents import Agent, Runner, SQLiteSession5758agent = Agent(59    name="Tour guide",60    instructions="Answer with compact travel facts.",61)6263session = SQLiteSession("conversation_123")646566async def main() -> None:67    first_turn = await Runner.run(68        agent,69        "What city is the Golden Gate Bridge in?",70        session=session,71    )72    print(first_turn.final_output)7374    second_turn = await Runner.run(75        agent,76        "What state is it in?",77        session=session,78    )79    print(second_turn.final_output)808182if __name__ == "__main__":83    asyncio.run(main())84```858687Sessions are the best default when you want durable memory, resumable approval flows, or storage that your application controls.8889Continue with server-managed state9091```javascript92import { Agent, run } from "@openai/agents";93import OpenAI from "openai";9495const agent = new Agent({96  name: "Assistant",97  instructions: "Reply very concisely.",98});99100const client = new OpenAI();101const { id: conversationId } = await client.conversations.create({});102103const first = await run(agent, "What city is the Golden Gate Bridge in?", {104  conversationId,105});106console.log(first.finalOutput);107108const second = await run(agent, "What state is it in?", {109  conversationId,110});111console.log(second.finalOutput);112```113114```python115import asyncio116117from agents import Agent, Runner118119agent = Agent(120    name="Assistant",121    instructions="Reply very concisely.",122)123124125async def main() -> None:126    first = await Runner.run(127        agent,128        "What city is the Golden Gate Bridge in?",129    )130    print(first.final_output)131132    second = await Runner.run(133        agent,134        "What state is it in?",135        previous_response_id=first.last_response_id,136    )137    print(second.final_output)138139140if __name__ == "__main__":141    asyncio.run(main())142```143144145Use `conversationId` when multiple systems should share one named conversation. Use `previousResponseId` in TypeScript or `previous_response_id` in Python when you want the cheapest response-to-response continuation option.146147## Stream runs incrementally148149Streaming uses the same agent loop and the same state strategies. The only difference is that you consume events while the run is still happening.150151Stream a run as text arrives152153```javascript154import { Agent, run } from "@openai/agents";155156const agent = new Agent({157  name: "Planet guide",158  instructions: "Answer with short facts.",159});160161const stream = await run(agent, "Give me three short facts about Saturn.", {162  stream: true,163});164165for await (const event of stream) {166  if (167    event.type === "raw_model_stream_event" &&168    event.data.type === "output_text_delta"169  ) {170    process.stdout.write(event.data.delta);171  }172}173174await stream.completed;175console.log("\nFinal:", stream.finalOutput);176```177178```python179import asyncio180181from openai.types.responses import ResponseTextDeltaEvent182183from agents import Agent, Runner184185agent = Agent(186    name="Planet guide",187    instructions="Answer with short facts.",188)189190191async def main() -> None:192    stream = Runner.run_streamed(193        agent,194        "Give me three short facts about Saturn.",195    )196197    async for event in stream.stream_events():198        if event.type == "raw_response_event" and isinstance(199            event.data, ResponseTextDeltaEvent200        ):201            print(event.data.delta, end="", flush=True)202203    print(f"\nFinal: {stream.final_output}")204205206if __name__ == "__main__":207    asyncio.run(main())208```209210211Three practical rules matter:212213- Wait for the stream to finish before treating the run as settled.214- If the run pauses for approval, resolve `interruptions` and resume from `state` rather than starting a fresh user turn.215- If you cancel a stream mid-turn, resume the unfinished turn from `state` if you want the same turn to continue later.216217## Handle pauses and failures deliberately218219Two broad classes of non-happy-path outcomes matter:220221- **Runtime or validation failures** such as max-turn limits, guardrail exceptions, or tool errors.222- **Expected pauses** such as human approval requests, where the run is intentionally interrupted and should later resume from the same state.223224Treat approvals as paused runs, not as new turns. That distinction keeps turn counts, history, and server-managed continuation IDs consistent.225226## Next steps227228Once the runtime loop is clear, move to the guide that matches the next workflow boundary you need to design.229230231232  [Results and state233234235236        Learn which result surfaces your application should carry into the next237      turn.](https://developers.openai.com/api/docs/guides/agents/results)238  [Orchestration and handoffs239240241242        Decide how multiple specialists behave inside the same runtime loop.](https://developers.openai.com/api/docs/guides/agents/orchestration)243  [Guardrails and human review244245246247        Add validation and approval pauses without breaking turn continuity.](https://developers.openai.com/api/docs/guides/agents/guardrails-approvals)
Files main
Menu

Theme