The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows in JavaScript/TypeScript. It is provider-agnostic, supporting OpenAI APIs and more.
Note
Looking for the Python version? Check out Agents SDK Python.
- Agents: LLMs configured with instructions, tools, guardrails, and handoffs.
- Handoffs: Specialized tool calls for transferring control between agents.
- Guardrails: Configurable safety checks for input and output validation.
- Tracing: Built-in tracking of agent runs, allowing you to view, debug, and optimize your workflows.
Explore the examples/ directory to see the SDK in action.
- Multi-Agent Workflows: Compose and orchestrate multiple agents in a single workflow.
- Tool Integration: Seamlessly call tools/functions from within agent responses.
- Handoffs: Transfer control between agents dynamically during a run.
- Structured Outputs: Support for both plain text and schema-validated structured outputs.
- Streaming Responses: Stream agent outputs and events in real time.
- Tracing & Debugging: Built-in tracing for visualizing and debugging agent runs.
- Guardrails: Input and output validation for safety and reliability.
- Parallelization: Run agents or tool calls in parallel and aggregate results.
- Human-in-the-Loop: Integrate human approval or intervention into workflows.
- Realtime Voice Agents: Build realtime voice agents using WebRTC or WebSockets
- Local MCP Server Support: Give an Agent access to a locally running MCP server to provide tools
- Separate optimized browser package: Dedicated package meant to run in the browser for Realtime agents.
- Broader model support: Use non-OpenAI models through the Vercel AI SDK adapter
- Long running functions: Suspend an agent loop to execute a long-running function and revive it later
- Voice pipeline: Chain text-based agents using speech-to-text and text-to-speech into a voice agent
- Node.js 22 or later
- Deno
- Bun
Experimental support:
- Cloudflare Workers with
nodejs_compatenabled
Check out the documentation for more detailed information.
npm install @openai/agents zod@3import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions: 'You are a helpful assistant',
});
const result = await run(
agent,
'Write a haiku about recursion in programming.',
);
console.log(result.finalOutput);
// Code within the code,
// Functions calling themselves,
// Infinite loop's dance.(If running this, ensure you set the OPENAI_API_KEY environment variable)
import { z } from 'zod';
import { Agent, run, tool } from '@openai/agents';
const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});
const agent = new Agent({
name: 'Data agent',
instructions: 'You are a data agent',
tools: [getWeatherTool],
});
async function main() {
const result = await run(agent, 'What is the weather in Tokyo?');
console.log(result.finalOutput);
}
main().catch(console.error);import { z } from 'zod';
import { Agent, run, tool } from '@openai/agents';
const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});
const dataAgent = new Agent({
name: 'Data agent',
instructions: 'You are a data agent',
handoffDescription: 'You know everything about the weather',
tools: [getWeatherTool],
});
// Use Agent.create method to ensure the finalOutput type considers handoffs
const agent = Agent.create({
name: 'Basic test agent',
instructions: 'You are a basic agent',
handoffs: [dataAgent],
});
async function main() {
const result = await run(agent, 'What is the weather in San Francisco?');
console.log(result.finalOutput);
}
main().catch(console.error);import { z } from 'zod';
import { RealtimeAgent, RealtimeSession, tool } from '@openai/agents-realtime';
const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});
const agent = new RealtimeAgent({
name: 'Data agent',
instructions: 'You are a data agent',
tools: [getWeatherTool],
});
// Intended to run in the browser
const { apiKey } = await fetch('/path/to/ephemeral/key/generation').then(
(resp) => resp.json(),
);
// Automatically configures audio input/output — start talking
const session = new RealtimeSession(agent);
await session.connect({ apiKey });The examples/ directory contains a series of examples to get started:
pnpm examples:basic- Basic example with handoffs and tool callingpnpm examples:agents-as-tools- Using agents as tools for translationpnpm examples:tools-web-search- Using the web search toolpnpm examples:tools-file-search- Using the file search toolpnpm examples:deterministic- Deterministic multi-agent workflowpnpm examples:parallelization- Running agents in parallel and picking the best resultpnpm examples:human-in-the-loop- Human approval for certain tool callspnpm examples:streamed- Streaming agent output and events in real timepnpm examples:streamed:human-in-the-loop- Streaming output with human-in-the-loop approvalpnpm examples:routing- Routing between agents based on language or contextpnpm examples:realtime-demo- Framework agnostic Voice Agent examplepnpm examples:realtime-next- Next.js Voice Agent example application
When you call Runner.run(), the SDK executes a loop until a final output is produced.
- The agent is invoked with the given input, using the model and settings configured on the agent (or globally).
- The LLM returns a response, which may include tool calls or handoff requests.
- If the response contains a final output (see below), the loop ends and the result is returned.
- If the response contains a handoff, the agent is switched to the new agent and the loop continues.
- If there are tool calls, the tools are executed, their results are appended to the message history, and the loop continues.
You can control the maximum number of iterations with the maxTurns parameter.
The final output is the last thing the agent produces in the loop.
- If the agent has an
outputType(structured output), the loop ends when the LLM returns a response matching that type. - If there is no
outputType(plain text), the first LLM response without tool calls or handoffs is considered the final output.
Summary of the agent loop:
- If the current agent has an
outputType, the loop runs until structured output of that type is produced. - If not, the loop runs until a message is produced with no tool calls or handoffs.
- If the maximum number of turns is exceeded, a
MaxTurnsExceededErroris thrown. - If a guardrail is triggered, a
GuardrailTripwireTriggeredexception is raised.
To view the documentation locally:
pnpm docs:devThen visit http://localhost:4321 in your browser.
If you want to contribute or edit the SDK/examples:
-
Install dependencies
pnpm install
-
Build the project
pnpm build && pnpm -r build-check -
Run tests and linter
pnpm test && pnpm lint
See AGENTS.md and CONTRIBUTING.md for the full contributor guide.
We'd like to acknowledge the excellent work of the open-source community, especially:
We're committed to building the Agents SDK as an open source framework so others in the community can expand on our approach.
For more details, see the documentation or explore the examples/ directory.
// Dette er en konseptuell implementasjonsguide. // Den viser hvordan du strukturerer et Genkit-prosjekt i henhold til // Mandala-Modellen for Agentisk Arkitektur (MAA).
// STEG 1: PROSJEKTOPPSETT OG STRUKTUR // ------------------------------------------------- // Start med å initialisere et nytt Genkit-prosjekt og installer nødvendige avhengigheter. // // Kjør i terminalen: // npm create genkit@latest my-agentic-system // cd my-agentic-system // npm install firebase-functions firebase-admin zod // // Prosjektstrukturen din vil se slik ut: // . // ├── genkit.ts // Hovedkonfigurasjon (Brahmasthan) // ├── src // │ ├── index.ts // Firebase Functions entrypoint (Øst/Vest-portene) // │ ├── flows // │ │ ├── orchestrator.ts // Hoved-orkestreringslogikk (Eter) // │ │ └── specialists.ts // Spesialist-agenter (f.eks. FrontendAgent) // │ └── lib // │ └── firestore.ts // Firestore-interaksjoner (Nord-porten) // │ └── types.ts // Datamodeller (Zod-schemas) // └── package.json
// STEG 2: HOVEDKONFIGURASJON (genkit.ts) // ------------------------------------------------- // Definer kjerne-agenten (Brahmasthan) og konfigurer Genkit.
import { configureGenkit } from '@genkit-ai/core'; import { firebase } from '@genkit-ai/firebase'; import { googleAI } from '@genkit-ai/googleai';
configureGenkit({ plugins: [ firebase(), // Aktiverer Firebase-integrasjon (for Cloud Functions, logging etc.) googleAI(), // Aktiverer Google AI-plugin for tilgang til Gemini ], logLevel: 'debug', enableTracingAndMetrics: true, });
// Definer din "Brahmasthan" - kjerne-modellen for de mest kritiske oppgavene. export const coreModel = 'gemini-1.5-pro-latest';
// STEG 3: DATAMODELLER (src/lib/types.ts) // ------------------------------------------------- // Bruk Zod for å definere robuste datastrukturer for arbeidsflyten.
import { z } from 'zod';
// Definerer en enkelt node i arbeidsflyten (inspirert av React Flow) export const WorkflowNodeSchema = z.object({ id: z.string(), type: z.enum(['agentNode', 'inputNode', 'outputNode']), data: z.object({ label: z.string(), // Spesifikke data for noden, f.eks. agentId, prompt, etc. agentId: z.string().optional(), prompt: z.string().optional(), }), position: z.object({ x: z.number(), y: z.number() }), });
// Definerer en kobling mellom to noder export const WorkflowEdgeSchema = z.object({ id: z.string(), source: z.string(), target: z.string(), });
// Definerer hele arbeidsflyten som sendes fra frontend export const WorkflowPayloadSchema = z.object({ userInput: z.string(), workflow: z.object({ nodes: z.array(WorkflowNodeSchema), edges: z.array(WorkflowEdgeSchema), }), projectId: z.string(), });
export type WorkflowPayload = z.infer;
// STEG 4: ORKESTRERINGS-FLOW (src/flows/orchestrator.ts) // ------------------------------------------------- // Dette er hjertet av systemet (Eter), som tolker og utfører arbeidsflyten.
import { defineFlow, run } from '@genkit-ai/flow'; import { WorkflowPayloadSchema } from '../lib/types'; import { callSpecialistAgent } from './specialists'; import * as z from 'zod';
// Nila Chakra: Kvalitetssjekk-agenten
export const qualityCheckFlow = defineFlow(
{
name: 'qualityCheckFlow',
inputSchema: z.object({
content: z.string(),
shikhara: z.string(), // Prosjektets hoveddirektiv
}),
outputSchema: z.object({
passed: z.boolean(),
feedback: z.string(),
}),
},
async ({ content, shikhara }) => {
// Implementer logikk for å vurdere output mot hoveddirektivet
// Dette er en forenklet versjon.
console.log(Kvalitetssjekk mot direktiv: "${shikhara}");
// I en ekte applikasjon ville du kalt Gemini her for en vurdering.
const passed = !content.toLowerCase().includes('error');
const feedback = passed ? "Kvalitet godkjent." : "Potensielt problem oppdaget.";
return { passed, feedback };
}
);
// Hoved-orkestreringsflyten export const orchestratorFlow = defineFlow( { name: 'orchestratorFlow', inputSchema: WorkflowPayloadSchema, outputSchema: z.string(), }, async (payload) => { console.log('Orkestreringsflyt startet for prosjekt:', payload.projectId);
// Her ville du implementert logikken for å traversere node-grafen.
// Dette er en forenklet, lineær demonstrasjon.
let currentInput = payload.userInput;
const workflowNodes = payload.workflow.nodes;
for (const node of workflowNodes) {
if (node.type === 'agentNode' && node.data.agentId) {
currentInput = await run('call-specialist-agent', () =>
callSpecialistAgent({
agentId: node.data.agentId!,
input: currentInput,
projectId: payload.projectId,
})
);
}
}
// Siste steg: Nila Chakra kvalitetskontroll
const shikhara = "Lag en effektiv og elegant løsning."; // Hentes fra Firestore i en ekte app
const qualityResult = await run('quality-check', () =>
qualityCheckFlow({ content: currentInput, shikhara })
);
if (!qualityResult.passed) {
console.warn('Kvalitetssjekk feilet:', qualityResult.feedback);
// Kan kaste en feil eller prøve å korrigere
return `Resultat generert, men med en advarsel: ${qualityResult.feedback}\n\nResultat: ${currentInput}`;
}
return currentInput;
} );
// STEG 5: SPESIALIST-AGENT FLOW (src/flows/specialists.ts) // ------------------------------------------------- // Definerer en gjenbrukbar flyt for å kalle en hvilken som helst spesialisert agent.
import { defineFlow, runFlow } from '@genkit-ai/flow'; import { generate } from '@genkit-ai/ai'; import { coreModel } from '../../genkit'; import * as z from 'zod'; // Importer en funksjon for å hente agent-konfigurasjon fra Firestore // import { getAgentConfig } from '../lib/firestore';
export const callSpecialistAgent = defineFlow(
{
name: 'callSpecialistAgent',
inputSchema: z.object({
agentId: z.string(),
input: z.string(),
projectId: z.string(),
}),
outputSchema: z.string(),
},
async ({ agentId, input, projectId }) => {
console.log(Kaller spesialist-agent: ${agentId} for prosjekt ${projectId});
// STEG 5a: Hent agent-konfigurasjon fra Firestore (Nord-porten)
// const agentConfig = await getAgentConfig(projectId, agentId);
// Hardkodet for eksempel:
const agentConfig = {
systemPrompt: `Du er en ${agentId}. Svar kort og konsist på følgende oppgave.`,
tools: [], // Her kan du legge til Genkit-verktøy
};
// STEG 5b: Kall Gemini-modellen (Brahmasthan)
const llmResponse = await generate({
model: coreModel,
prompt: input,
system: agentConfig.systemPrompt,
config: { temperature: 0.5 },
});
return llmResponse.text();
} );
// STEG 6: KOBLE TIL FIREBASE (src/index.ts) // ------------------------------------------------- // Gjør Genkit-flyten tilgjengelig som en HTTP-trigget Cloud Function. // Dette er dine Øst/Vest-porter.
import { onFlow } from '@genkit-ai/firebase/functions'; import { orchestratorFlow } from './flows/orchestrator';
// Eksporter flyten slik at Firebase kan deploye den som en Cloud Function. // Frontend kan nå kalle denne funksjonen via Firebase SDK. export const runWorkflow = onFlow( { name: 'runWorkflow', // Navnet på Cloud Function ...orchestratorFlow, // Bruker schema og logikk fra orchestratorFlow }, async (payload) => { // Kjører selve orkestreringsflyten return await orchestratorFlow(payload); } );
// For å deploye, kjør: // firebase deploy --only functions
