Aiconomist.in
AI Development

Apr 08, 2025

Building Your First AI Agent with OpenAI's Agents SDK: A Step-by-Step Guide

Building Your First AI Agent with OpenAI's Agents SDK: A Step-by-Step Guide
— scroll down — read more

Building Your First AI Agent with OpenAI's Agents SDK: A Step-by-Step Guide

The release of OpenAI's Agents SDK has fundamentally transformed how developers can build advanced AI systems. This powerful toolkit enables the creation of autonomous agents that can reason about complex problems, develop execution plans, and interact with external systems—all while maintaining context across multi-step workflows. In this comprehensive guide, we'll walk through the process of building your first AI agent using OpenAI's Agents SDK, from basic setup to advanced deployment.

Understanding the Agents SDK Architecture

The OpenAI Agents SDK provides a structured framework for building AI agents that can accomplish complex tasks through reasoning and tool use. Before diving into implementation, it's important to understand the core components:

Key Components

  1. Agent Core: The central reasoning engine, typically powered by GPT-4 or newer models
  2. Tool Registry: A collection of functions the agent can call to interact with external systems
  3. Memory System: Manages context and information retention across interaction turns
  4. Planning Module: Enables the agent to break down complex tasks into manageable steps
  5. Execution Engine: Handles the actual execution of tool calls and action sequences

This architecture enables agents to move beyond simple question-answering to become genuine assistants that can perform meaningful work in the real world.

Setting Up Your Development Environment

Let's start by setting up a development environment for building agents:

1# Create a new project directory
2mkdir my-first-openai-agent
3cd my-first-openai-agent
4
5# Initialize a new Node.js project
6npm init -y
7
8# Install the OpenAI Agents SDK and dependencies
9npm install @openai/agents-sdk @openai/openai-api dotenv express
10
11# Create configuration files
12touch .env
13touch agent.js
14touch server.js
15

Configure your environment variables in the .env file:

1OPENAI_API_KEY=your_openai_api_key
2AGENT_PORT=3000
3

Creating Your First Basic Agent

Let's start with a simple agent that can perform basic reasoning and answer questions:

1// agent.js
2require('dotenv').config();
3const { OpenAI } = require('@openai/openai-api');
4const { Agent, ToolRegistry } = require('@openai/agents-sdk');
5
6// Initialize OpenAI client
7const openai = new OpenAI({
8  apiKey: process.env.OPENAI_API_KEY
9});
10
11// Create a new tool registry
12const toolRegistry = new ToolRegistry();
13
14// Create and configure the agent
15const createAgent = async () => {
16  const agent = new Agent({
17    name: "ResearchAssistant",
18    description: "I help users find information and answer questions.",
19    model: "gpt-4o",
20    tools: toolRegistry,
21    openai: openai
22  });
23  
24  // Initialize the agent
25  await agent.init();
26  
27  return agent;
28};
29
30module.exports = { createAgent };
31

Now, let's create a simple server to interact with our agent:

1// server.js
2const express = require('express');
3const { createAgent } = require('./agent');
4
5const app = express();
6app.use(express.json());
7
8let agent;
9
10// Initialize the agent
11(async () => {
12  agent = await createAgent();
13  console.log("Agent initialized successfully!");
14})();
15
16// Endpoint to interact with the agent
17app.post('/chat', async (req, res) => {
18  try {
19    const { message, sessionId } = req.body;
20    
21    if (!message) {
22      return res.status(400).json({ error: "Message is required" });
23    }
24    
25    const response = await agent.chat({
26      message,
27      sessionId: sessionId || 'default-session'
28    });
29    
30    res.json({ response });
31  } catch (error) {
32    console.error("Error:", error);
33    res.status(500).json({ error: "An error occurred while processing your request" });
34  }
35});
36
37const PORT = process.env.AGENT_PORT || 3000;
38app.listen(PORT, () => {
39  console.log(`Agent server running on port ${PORT}`);
40});
41

This gives us a basic agent accessible via an API endpoint, but it doesn't yet have special capabilities beyond conversation.

Adding Tool Capabilities to Your Agent

The real power of the Agents SDK comes from giving your agent the ability to use tools. Let's add some useful tools to our agent:

1// tools.js
2const axios = require('axios');
3const { Tool, Parameter, ParameterType } = require('@openai/agents-sdk');
4
5// Web Search Tool
6const webSearchTool = new Tool({
7  name: 'web_search',
8  description: 'Search the web for current information',
9  parameters: [
10    new Parameter({
11      name: 'query',
12      type: ParameterType.STRING,
13      description: 'The search query',
14      required: true
15    })
16  ],
17  execute: async ({ query }) => {
18    try {
19      // This would typically connect to a real search API
20      const response = await axios.get('https://api.searchprovider.com/search', {
21        params: { q: query, api_key: process.env.SEARCH_API_KEY }
22      });
23      
24      return response.data.results.map(result => ({
25        title: result.title,
26        url: result.url,
27        snippet: result.snippet
28      }));
29    } catch (error) {
30      return { error: 'Failed to perform web search', details: error.message };
31    }
32  }
33});
34
35// Weather Information Tool
36const weatherTool = new Tool({
37  name: 'get_weather',
38  description: 'Get current weather information for a location',
39  parameters: [
40    new Parameter({
41      name: 'location',
42      type: ParameterType.STRING,
43      description: 'The city and country, e.g., "New York, USA"',
44      required: true
45    })
46  ],
47  execute: async ({ location }) => {
48    try {
49      const response = await axios.get('https://api.weatherprovider.com/current', {
50        params: { location, api_key: process.env.WEATHER_API_KEY }
51      });
52      
53      return {
54        temperature: response.data.temperature,
55        conditions: response.data.conditions,
56        humidity: response.data.humidity,
57        wind: response.data.wind
58      };
59    } catch (error) {
60      return { error: 'Failed to retrieve weather information', details: error.message };
61    }
62  }
63});
64
65module.exports = { webSearchTool, weatherTool };
66

Now, update your agent.js file to register these tools:

1// agent.js (updated)
2require('dotenv').config();
3const { OpenAI } = require('@openai/openai-api');
4const { Agent, ToolRegistry } = require('@openai/agents-sdk');
5const { webSearchTool, weatherTool } = require('./tools');
6
7// Initialize OpenAI client
8const openai = new OpenAI({
9  apiKey: process.env.OPENAI_API_KEY
10});
11
12// Create a new tool registry and register tools
13const toolRegistry = new ToolRegistry();
14toolRegistry.register(webSearchTool);
15toolRegistry.register(weatherTool);
16
17// Create and configure the agent
18const createAgent = async () => {
19  const agent = new Agent({
20    name: "ResearchAssistant",
21    description: "I help users find information, answer questions, and check weather conditions.",
22    model: "gpt-4o", 
23    tools: toolRegistry,
24    openai: openai
25  });
26  
27  // Initialize the agent
28  await agent.init();
29  
30  return agent;
31};
32
33module.exports = { createAgent };
34

Implementing Advanced Memory and State Management

To build truly useful agents, we need to implement proper memory and state management:

1// memory.js
2class AgentMemory {
3  constructor() {
4    this.sessions = new Map();
5  }
6  
7  // Initialize a new session
8  createSession(sessionId) {
9    if (!this.sessions.has(sessionId)) {
10      this.sessions.set(sessionId, {
11        conversationHistory: [],
12        userData: {},
13        taskState: {}
14      });
15    }
16    return this.getSession(sessionId);
17  }
18  
19  // Get an existing session
20  getSession(sessionId) {
21    if (!this.sessions.has(sessionId)) {
22      return this.createSession(sessionId);
23    }
24    return this.sessions.get(sessionId);
25  }
26  
27  // Add a message to the conversation history
28  addMessage(sessionId, role, content) {
29    const session = this.getSession(sessionId);
30    session.conversationHistory.push({ role, content, timestamp: new Date() });
31    
32    // Trim history if needed to manage context length
33    if (session.conversationHistory.length > 20) {
34      session.conversationHistory = session.conversationHistory.slice(-20);
35    }
36  }
37  
38  // Store user-specific data
39  setUserData(sessionId, key, value) {
40    const session = this.getSession(sessionId);
41    session.userData[key] = value;
42  }
43  
44  // Store task state for multi-step operations
45  setTaskState(sessionId, key, value) {
46    const session = this.getSession(sessionId);
47    session.taskState[key] = value;
48  }
49  
50  // Get full context for agent
51  getContext(sessionId) {
52    const session = this.getSession(sessionId);
53    return {
54      conversationHistory: session.conversationHistory,
55      userData: session.userData,
56      taskState: session.taskState
57    };
58  }
59}
60
61module.exports = new AgentMemory();
62

Now, update your agent to use this memory system:

1// agent.js (with memory)
2const memory = require('./memory');
3
4// Inside the agent's chat method
5const response = await agent.chat({
6  message,
7  sessionId,
8  context: memory.getContext(sessionId)
9});
10
11// Save the interaction
12memory.addMessage(sessionId, 'user', message);
13memory.addMessage(sessionId, 'assistant', response.content);
14
15// Update any task state if needed
16if (response.taskState) {
17  Object.entries(response.taskState).forEach(([key, value]) => {
18    memory.setTaskState(sessionId, key, value);
19  });
20}
21

Implementing Multi-Step Planning

One of the most powerful capabilities of the Agents SDK is enabling agents to plan and execute multi-step tasks. Let's implement this functionality:

1// planning.js
2const { PlanningModule } = require('@openai/agents-sdk');
3
4const createPlanningModule = (agent) => {
5  return new PlanningModule({
6    agent: agent,
7    planningStrategy: 'recursive', // can be 'sequential', 'recursive', or 'adaptive'
8    maxPlanningSteps: 5,
9    maxExecutionSteps: 10,
10    planningPrompt: `
11      You are an AI assistant that creates plans to solve user tasks efficiently.
12      Based on the user's request, create a detailed plan with specific steps.
13      Each step should be concrete and actionable.
14      If a step requires using a tool, specify which tool to use and what parameters to provide.
15    `
16  });
17};
18
19module.exports = { createPlanningModule };
20

Update your agent to use planning:

1// agent.js (with planning)
2const { createPlanningModule } = require('./planning');
3
4// Inside createAgent function
5const agent = new Agent({
6  // ... existing configuration
7});
8
9await agent.init();
10
11// Add planning capability
12const planningModule = createPlanningModule(agent);
13agent.usePlanning(planningModule);
14
15return agent;
16

Building a Real-World Example: Research Assistant Agent

Now let's put everything together to build a practical research assistant agent that can:

  1. Search for information online
  2. Extract and summarize key points
  3. Save research findings
  4. Generate reports based on collected information

First, let's add more specialized tools:

1// research-tools.js
2const fs = require('fs').promises;
3const path = require('path');
4const { Tool, Parameter, ParameterType } = require('@openai/agents-sdk');
5
6// Tool to save research findings
7const saveResearchTool = new Tool({
8  name: 'save_research_finding',
9  description: 'Save an important research finding to the research database',
10  parameters: [
11    new Parameter({
12      name: 'topic',
13      type: ParameterType.STRING,
14      description: 'The research topic',
15      required: true
16    }),
17    new Parameter({
18      name: 'finding',
19      type: ParameterType.STRING,
20      description: 'The research finding to save',
21      required: true
22    }),
23    new Parameter({
24      name: 'source',
25      type: ParameterType.STRING,
26      description: 'The source of the information (URL, book, etc.)',
27      required: true
28    })
29  ],
30  execute: async ({ topic, finding, source }) => {
31    try {
32      // Ensure research directory exists
33      const researchDir = path.join(__dirname, 'research');
34      await fs.mkdir(researchDir, { recursive: true });
35      
36      // Create or append to topic file
37      const topicFile = path.join(researchDir, `${topic.replace(/[^a-z0-9]/gi, '_')}.json`);
38      
39      let topicData = [];
40      try {
41        const existingData = await fs.readFile(topicFile, 'utf8');
42        topicData = JSON.parse(existingData);
43      } catch (err) {
44        // File doesn't exist yet, will create new one
45      }
46      
47      // Add new finding
48      topicData.push({
49        finding,
50        source,
51        timestamp: new Date().toISOString()
52      });
53      
54      // Save updated data
55      await fs.writeFile(topicFile, JSON.stringify(topicData, null, 2));
56      
57      return { success: true, message: `Finding saved to topic "${topic}"` };
58    } catch (error) {
59      return { error: 'Failed to save research finding', details: error.message };
60    }
61  }
62});
63
64// Tool to generate a research report
65const generateReportTool = new Tool({
66  name: 'generate_research_report',
67  description: 'Generate a formatted research report from saved findings on a topic',
68  parameters: [
69    new Parameter({
70      name: 'topic',
71      type: ParameterType.STRING,
72      description: 'The research topic to generate a report for',
73      required: true
74    }),
75    new Parameter({
76      name: 'format',
77      type: ParameterType.STRING,
78      description: 'The desired format of the report (markdown, text, html)',
79      required: true
80    })
81  ],
82  execute: async ({ topic, format }) => {
83    try {
84      // Read findings for the topic
85      const topicFile = path.join(__dirname, 'research', `${topic.replace(/[^a-z0-9]/gi, '_')}.json`);
86      const topicData = JSON.parse(await fs.readFile(topicFile, 'utf8'));
87      
88      // Generate the report
89      let report = '';
90      
91      if (format === 'markdown') {
92        report = `# Research Report: ${topic}\n\n`;
93        report += `*Generated on ${new Date().toLocaleDateString()}*\n\n`;
94        report += `## Key Findings\n\n`;
95        
96        topicData.forEach((item, index) => {
97          report += `### Finding ${index + 1}\n\n`;
98          report += `${item.finding}\n\n`;
99          report += `**Source:** ${item.source}\n\n`;
100        });
101      } else if (format === 'html') {
102        // HTML format implementation
103        report = `<h1>Research Report: ${topic}</h1>`;
104        // Add more HTML formatting
105      } else {
106        // Plain text format
107        report = `RESEARCH REPORT: ${topic}\n\n`;
108        // Add more text formatting
109      }
110      
111      // Save the report
112      const reportFile = path.join(__dirname, 'research', `${topic.replace(/[^a-z0-9]/gi, '_')}_report.${format === 'html' ? 'html' : 'md'}`);
113      await fs.writeFile(reportFile, report);
114      
115      return { 
116        success: true, 
117        message: `Report generated for topic "${topic}"`,
118        reportPath: reportFile,
119        reportPreview: report.substring(0, 500) + (report.length > 500 ? '...' : '')
120      };
121    } catch (error) {
122      return { error: 'Failed to generate research report', details: error.message };
123    }
124  }
125});
126
127module.exports = { saveResearchTool, generateReportTool };
128

Now, let's update our agent to use these research-specific tools:

1// research-agent.js
2require('dotenv').config();
3const { OpenAI } = require('@openai/openai-api');
4const { Agent, ToolRegistry } = require('@openai/agents-sdk');
5const { webSearchTool, weatherTool } = require('./tools');
6const { saveResearchTool, generateReportTool } = require('./research-tools');
7const memory = require('./memory');
8const { createPlanningModule } = require('./planning');
9
10// Initialize OpenAI client
11const openai = new OpenAI({
12  apiKey: process.env.OPENAI_API_KEY
13});
14
15// Create a new tool registry and register all tools
16const toolRegistry = new ToolRegistry();
17toolRegistry.register(webSearchTool);
18toolRegistry.register(weatherTool);
19toolRegistry.register(saveResearchTool);
20toolRegistry.register(generateReportTool);
21
22// Create the research agent
23const createResearchAgent = async () => {
24  const agent = new Agent({
25    name: "ResearchAssistant",
26    description: `I am a research assistant that can help with information gathering, 
27                  fact-checking, and report generation. I can search the web for current
28                  information, save important findings, and compile research reports.`,
29    model: "gpt-4o",
30    tools: toolRegistry,
31    openai: openai,
32    systemPrompt: `As a research assistant, your primary goal is to help users gather
33                   and organize information on topics they're interested in. When asked
34                   about a topic, follow these steps:
35                   1. Understand the user's research needs and goals
36                   2. Search for relevant and up-to-date information
37                   3. Extract key facts and findings
38                   4. Save important information for later reference
39                   5. Summarize what you've learned
40                   6. Generate reports when requested
41                   
42                   Always cite sources for information you provide, and prioritize
43                   credible sources. Be transparent about the limitations of your
44                   knowledge and the information you find.`
45  });
46  
47  // Initialize the agent
48  await agent.init();
49  
50  // Add planning capability
51  const planningModule = createPlanningModule(agent);
52  agent.usePlanning(planningModule);
53  
54  return agent;
55};
56
57// Handle agent interaction with memory management
58const interactWithAgent = async (message, sessionId = 'default-session') => {
59  const agent = await createResearchAgent();
60  
61  // Get session context
62  const context = memory.getContext(sessionId);
63  
64  // Process the message
65  const response = await agent.chat({
66    message,
67    sessionId,
68    context
69  });
70  
71  // Update memory
72  memory.addMessage(sessionId, 'user', message);
73  memory.addMessage(sessionId, 'assistant', response.content);
74  
75  // Update task state if needed
76  if (response.taskState) {
77    Object.entries(response.taskState).forEach(([key, value]) => {
78      memory.setTaskState(sessionId, key, value);
79    });
80  }
81  
82  return response;
83};
84
85module.exports = { createResearchAgent, interactWithAgent };
86

Deployment and Monitoring

To deploy your agent in a production environment, you'll need proper monitoring and logging:

1// monitoring.js
2const winston = require('winston');
3
4// Create logger
5const logger = winston.createLogger({
6  level: 'info',
7  format: winston.format.combine(
8    winston.format.timestamp(),
9    winston.format.json()
10  ),
11  defaultMeta: { service: 'research-agent' },
12  transports: [
13    new winston.transports.File({ filename: 'error.log', level: 'error' }),
14    new winston.transports.File({ filename: 'combined.log' })
15  ]
16});
17
18// Add console logging in development
19if (process.env.NODE_ENV !== 'production') {
20  logger.add(new winston.transports.Console({
21    format: winston.format.simple()
22  }));
23}
24
25// Agent activity monitoring
26const monitorAgent = (agent) => {
27  // Log all agent actions
28  agent.on('action', (action) => {
29    logger.info('Agent action', { action });
30  });
31  
32  // Log all tool executions
33  agent.on('toolExecution', (tool, params, result) => {
34    logger.info('Tool execution', { 
35      tool: tool.name, 
36      params, 
37      success: !result.error,
38      resultSummary: result.error ? result.error : 'Success'
39    });
40  });
41  
42  // Log errors
43  agent.on('error', (error) => {
44    logger.error('Agent error', { error: error.message, stack: error.stack });
45  });
46  
47  return agent;
48};
49
50module.exports = { logger, monitorAgent };
51

Update your server to include monitoring:

1// server.js (with monitoring)
2const express = require('express');
3const { createResearchAgent, interactWithAgent } = require('./research-agent');
4const { logger, monitorAgent } = require('./monitoring');
5
6const app = express();
7app.use(express.json());
8
9let agent;
10
11// Initialize the agent with monitoring
12(async () => {
13  try {
14    agent = await createResearchAgent();
15    monitorAgent(agent);
16    logger.info("Agent initialized successfully!");
17  } catch (error) {
18    logger.error("Failed to initialize agent", { error: error.message });
19  }
20})();
21
22// Add request logging middleware
23app.use((req, res, next) => {
24  const start = Date.now();
25  res.on('finish', () => {
26    const duration = Date.now() - start;
27    logger.info('API request', {
28      method: req.method,
29      path: req.path,
30      statusCode: res.statusCode,
31      duration: `${duration}ms`
32    });
33  });
34  next();
35});
36
37// Endpoint to interact with the agent
38app.post('/chat', async (req, res) => {
39  try {
40    const { message, sessionId = 'default-session' } = req.body;
41    
42    if (!message) {
43      return res.status(400).json({ error: "Message is required" });
44    }
45    
46    logger.info('Chat request received', { sessionId, messagePreview: message.substring(0, 50) });
47    
48    const response = await interactWithAgent(message, sessionId);
49    res.json({ response });
50  } catch (error) {
51    logger.error("Error in chat endpoint", { error: error.message });
52    res.status(500).json({ error: "An error occurred while processing your request" });
53  }
54});
55
56// Health check endpoint
57app.get('/health', (req, res) => {
58  if (agent) {
59    res.json({ status: 'healthy', agent: agent.name });
60  } else {
61    res.status(503).json({ status: 'initializing' });
62  }
63});
64
65const PORT = process.env.AGENT_PORT || 3000;
66app.listen(PORT, () => {
67  logger.info(`Agent server running on port ${PORT}`);
68});
69

Performance Optimization and Scaling

For production deployment, consider these optimization strategies:

1// optimization.js
2const cacheManager = require('cache-manager');
3const redisStore = require('cache-manager-redis-store');
4
5// Create a Redis cache
6const redisCache = cacheManager.caching({
7  store: redisStore,
8  host: process.env.REDIS_HOST || 'localhost',
9  port: process.env.REDIS_PORT || 6379,
10  ttl: 600 // Time to live in seconds
11});
12
13// Optimize web search with caching
14const optimizeWebSearch = (searchTool) => {
15  const originalExecute = searchTool.execute;
16  
17  searchTool.execute = async (params) => {
18    const cacheKey = `web_search:${JSON.stringify(params)}`;
19    
20    try {
21      // Try to get from cache first
22      const cachedResult = await redisCache.get(cacheKey);
23      if (cachedResult) {
24        return cachedResult;
25      }
26      
27      // If not in cache, execute original function
28      const result = await originalExecute(params);
29      
30      // Store in cache
31      await redisCache.set(cacheKey, result);
32      
33      return result;
34    } catch (error) {
35      // If cache fails, just execute original function
36      return originalExecute(params);
37    }
38  };
39  
40  return searchTool;
41};
42
43module.exports = { optimizeWebSearch };
44

Conclusion and Next Steps

In this comprehensive guide, we've covered the essential steps for building AI agents with OpenAI's Agents SDK:

  1. Setting up the development environment
  2. Creating a basic agent
  3. Adding tool capabilities
  4. Implementing memory and state management
  5. Adding multi-step planning
  6. Building a specialized research assistant
  7. Deploying with monitoring and optimization

This foundation gives you the skills to build powerful AI agents that can tackle complex tasks across a wide range of domains. As you continue developing with the Agents SDK, consider these advanced techniques:

  • Implementing conversational memory with summarization for longer interactions
  • Creating domain-specific tools for specialized applications
  • Developing multi-agent systems where agents collaborate on complex tasks
  • Integrating with enterprise systems via secure API connections
  • Implementing fine-tuned models for domain-specific knowledge

The Agents SDK opens up a new frontier in AI development, enabling applications that go beyond simple chat interfaces to become truly useful digital assistants that can understand, plan, and execute tasks in the real world.

Ready to take your AI agent development to the next level? Check out our advanced Agents SDK tutorials or join our developer community to share your experiences and learn from others.


Share this post