ToCode
Kanalga Telegramโda oโtish
ืืืคืื ืงืฆืจืื ืืืชืื ืชืื ืืืช ืื ืื ืคืจืง
Ko'proq ko'rsatish1 419
Obunachilar
Ma'lumot yo'q24 soatlar
Ma'lumot yo'q7 kunlar
-430 kunlar
Postlar arxiv
1 419
ืืืจื ืืชืงื ืช ืืกืคืจืืืช ืืืืืจืช ืืฉืชื ื ืืกืืืื
OPENAI_API_KEY ื ืืื ืืืชืงืื ืืงืืืฅ route.ts ืืืขืืื ืืืชื ืืชืืื ืืื:
import { Agent, run } from '@openai/agents';
const agent = new Agent({
name: 'Assistant',
instructions: 'You are a helpful assistant',
});
export async function POST() {
const result = await run(agent, 'Tell me a story about a cat.', {
stream: true,
});
// Convert the result to a standard ReadableStream
const stream = new ReadableStream({
async start(controller) {
const encoder = new TextEncoder();
try {
for await (const event of result) {
if (event.type === 'raw_model_stream_event') {
if (event.data.type === "output_text_delta") {
controller.enqueue(encoder.encode(event.data.delta));
}
}
}
} catch (error) {
controller.error(error);
} finally {
controller.close();
}
},
});
return new Response(stream, {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Transfer-Encoding': 'chunked',
},
});
}
ืงืื ืืฆืืจืช ืืกืืื ืฆืจืื ืืืืจืืืช ืืื ืืืืจ ืื ืืื ืืืืืง ืืืืื ืฉื ืงืื ืืคืืืชืื ืฉืืืจื ื ืืคืืกืืื ืงืืืืื ืืกืืืจื. ืงืื ืืืืจืื ืืืื ืืืจ ืืื ืจืขืืื ืืช ืืืฉืื. ืชืืืื ืื ืื ื ืฉืืื ืื ืืืคืชื stream ืฉืืืคืืข ืืืคืฉืจืืืืช ืฉืื ื ืืขืืืจ ื run:
const result = await run(agent, 'Tell me a story about a cat.', {
stream: true,
});
ืืคืืืชืื ืืฉืชืืฉืชื ืืคืื ืงืฆืื ืืืจืช ืืื ืืจืืฅ ืืืฆื ืืืจืื ืืื ืืืื ืจืืฉืื ืืื ืืกืคืจืืืช.
ืืืืจืื ืขืฆืื ืืืจืฉืช ืืืืืช for async ืฉื ืจืืืช ืื:
const stream = new ReadableStream({
async start(controller) {
const encoder = new TextEncoder();
try {
for await (const event of result) {
if (event.type === 'raw_model_stream_event') {
if (event.data.type === "output_text_delta") {
controller.enqueue(encoder.encode(event.data.delta));
}
}
}
} catch (error) {
controller.error(error);
} finally {
controller.close();
}
},
});
ืงืจืืืช ืืืจืืขืื ืืกืืื ืืกืื ืืจืื ื ืืืืฆืขืช ืขื ืืืืืช for async ืืื ืคืขื ืฉืืฉ ืืืจืืข ื ืืกืฃ ื ืื ืกืื ืืืืฃ ืืืืืื. ืขืืืจ ืื ืืืจืืข ืื ื ืืืืง ืืช ืืกืื ืฉืื, ืืืื ืืืชื ืกืืืื ืฉืืืจื ื ืืชืืื ืืฉืจืืื ื ืืื ืืืืจืื ืืืืข ืืชืืื ืืช ืคืืืชืื, ืจืง ืฉืืคืขื ืืืชืืื ืืชืฉืืืช ื HTTP ืื ื ืขืฉืืช ืขื yield ืืื ืืคืืืชืื ืืื ืขื controller.enqueue.
ืฉืืื ืขื ืกืืื - ื ืืืื ืืืกืืืจืื
ืืืชืืจ ืืืืจืื ืฉืื ื ืืืืฉืง ืืื ืืืฆืืจ ืฉืืื - ืืงืืช ืืืืขื ืืืืฉืชืืฉ, ืืฉืืื ืืืชื ืืกืืื, ืืฉืืืจ ืืช ืืชืฉืืื ืฉื ืืกืืื ืืืืืืขื ืืืื ืืฉืืื ืืช ืื ืืืืกืืืจืื ืืฆืืจืืฃ ืืืืืขื.
ืืคืืืชืื ืืืืื ื ืืฉืืืจ ืืช ืืืกืืืจืืืช ืืฉืืืืช ืืฆื ืฉืจืช ืืืืฆืขืืช session. ื TypeScript ืกืคืจืืืช ืืกืืื ืื ืื ืชืืืืช ื Session ืืืื ื ืฆืืจื ืืื ืืช ืืช ืืื ืื ืื ืืขืฆืื ื. ืื ืื ื ืืืืืื ืืืืืจ ืื ืืฉืืืจ ืืืืขืืช ืืฉื ืืช ืืืกืืก ื ืชืื ืื, ืืืืืจืื ืืฆื ืฉืจืช ืื ืืฆื ืืงืื. ืืืืืื ืืืื ืื ื ืืืืจ ืืฉืืืจ ืืช ืื ืืืืืขืืช ืืฆื ืืงืื ืคืฉืื ืื ืื ืงื ืืืืืืฉ ืืืืืื ืื ืื ืืฉื ื ืืกืคืจืืืช ืืกืืื ืื.
ืื ืงืื ืฆื ืืืงืื ืืืขืืืื:
'use client';
import { FormEvent, useState } from "react";
type Message = {role: string, content: string };
export default function Home() {
const [messages, setMessages] = useState<Array<Message>>([]);
async function sendMessage(ev: FormEvent) {
ev.preventDefault();
const form = ev.target as HTMLFormElement;
const fd = new FormData(form);
const userMessage = { role: 'user', content: fd.get('message') as string };
setMessages(prev => [...prev,
userMessage,
{ role: 'assistant', content: '' }
]);
form.reset();
try {
const response = await fetch('/chat', {
method: "POST",
body: JSON.stringify([...messages, userMessage]),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
setMessages(prev => prev.with(-1, {1 419
ืืื 9 - ืืืื ื ื ืกื ืืช ืื ืืืืืคืกืงืจืืคื
ืกืคืจืืืช OpenAI Agents SDK ืืืื ื ืื ืืืืจืกืช ืืืืคืกืงืจืืคื ืืืคืฉืจ ืืืฉืชืืฉ ืื ืืฉืืืชืืื ืืืฉืืื next.js. ื ืืื, ืื ื vercel ืืฉ ืกืคืจืืืช ืกืืื ืื ืืื ืืืชื ืืคืฉืจ ืืืืจ ืืงืืืช ื next.js, ืืื ืชืืื ืืื ืฉืืฉ ืืื ืืคืฉืจืืืืช.
ืืคืืกื ืื ื ืจืื ืืื ืืืฆืืจ ืืืฉืื next.js ืืฉืืื ืขื ืกืืื ืืืืฆืขืืช ืกืคืจืืืช OpenAI Agents SDK ืชืื ืฉืืืืฉ ืืืืจืื ืฉืืืื ื ืืืชืืืชื ืืืืืคืกืงืจืืคื.
ืืื ืขืืื Streaming ื Next.JS
ืืืชืืจ ืืจืืฉืื ืืคืืชืื ืืืฉืง ืืื ืืกืืื ืื ืืื ืืืืชื ื ืืืจืืื ืืื ืืืืขื ืฉืื ื ืฉืืื ืืืื ืชืฉืืืช ืืกืืื. ืืืื ืฉืืืชืื ืื ืื ืื ื ืืืืืื ืืืฆืื ืืืฉืชืืฉืื ืืช ืืืงืกื ืฉืืกืืื ืืืืฆืจ ื Streaming ืืื ืฉืืคืืืช ืื ืืืื ืืื ืืฉืขืื.
ื Next.JS ืืืจืืช ืืืืข ืขืืืืช ืืืืคื ืืื:
1. ืื ืื ื ืืืืืจืื API Route ืืืืฉืื ืฉืืืืืจ ReadableStream.
2. ืื ืื ื ืืืชืืื ืืฆืืจื ืืกืื ืืจืื ืืช ื Stream.
3. ืืฉืืงืื ืคืื ื ืขื fetch ืื ืชืื ืื ืืื ืืงืื ืชืฉืืื ืฉืืืืื ืืช ืืืืชืจืช:
transfer-encoding: chunked
4. ืืืืืข ืขืฆืื ืืืืข ืืืืงืื ืืฉืืื ืืืื. ืืฆื ืืงืื ื ืืื ืืืฆืืจ Reader ืืืงืจืื ืืคืื ืงืฆืื reader.read() ืืืืืื. ืคืื ืงืฆืื ืื ืืืืืจื ืืช ื chunk-ืื ืฉื ืืืืืขื ืืืฉืจืช ืืืืจืื ืืฉืื ืืืื ืื.
ืงืื? ืืื. ืื ื ืืืฆืจ ืืคืืืงืฆืืืช next.js ืืืฉื ืืคืืชื ืงืืืฅ src/app/chat/route.ts ืขื ืืชืืื ืืื:
export async function POST() {
const encoder = new TextEncoder();
const customReadable = new ReadableStream({
async start(controller) {
controller.enqueue(encoder.encode('Processing...'));
await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate delay
controller.enqueue(encoder.encode('Verifying hash...'));
await new Promise(resolve => setTimeout(resolve, 1500));
controller.enqueue(encoder.encode('Scanning file...'));
await new Promise(resolve => setTimeout(resolve, 2000));
controller.enqueue(encoder.encode('Generating link...'));
controller.close(); // Signal end of stream
},
});
return new Response(customReadable, {
headers: {
'Content-Type': 'text/plain',
'Transfer-Encoding': 'chunked',
},
});
}
ืื ืงืจืืื ื:
controller.enqueue(encoder.encode('Processing...'));
ืืืชืืช ืืืืขื ืืืฉื ื Stream ืืืืืจืช ื Stream ืืกืืฃ ืืคืื ืงืฆืื ืืืืืื ืฉืืืคืืคื ืืืื ืืงืจืื ืืช ืืืืืข ืืื ื ืืฉืืืืืข ื ืืฆืจ.
ืืฆื ืืืงืื ืื ื ืืขืืื ืืช ืืงืืืฅ page.tsx ืืชืืื ืืื:
'use client';
import { FormEvent, useState } from "react";
export default function Home() {
const [streamedText, setStreamedText] = useState('');
async function startStreaming(ev: FormEvent) {
ev.preventDefault();
try {
const response = await fetch('/chat', {
method: "POST"
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
setStreamedText(prev => prev + decoder.decode(value));
}
} catch (error) {
console.error('Streaming error:', error);
}
setStreamedText(prev => prev + 'Done!');
}
return (
<div >
<main >
<p>{streamedText}</p>
<form onSubmit={startStreaming}>
<input type="text" />
<input type="submit" value="Send" />
</form>
</main>
</div>
);
}
ืืฉืืืืง ืฉืขืืกืง ืืืืจืืช ืืชืฉืืื ืืื:
const response = await fetch('/chat', {
method: "POST"
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
setStreamedText(prev => prev + decoder.decode(value));
}
ืืคืขืืชื fetch, ืื ืืชื Reader ืืืชืฉืืื ืืื ื ืงืืจื ืืืืืื ื reader.read ืขื ืฉืืฉืจืช ืืกืืื ืืช ืืืืจืื. ืื ืคืขื ืฉืืืืจื ืืืืข ื ืืกืฃ ืื ื ืืขืืื ืืฉืชื ื state ืฉืืืจืื ืืืืืข ืืืืฉ ืืืืคืืข ืขื ืืืกื.
ืืืจืืช ืืืืข ืืกืืื
ื ืืกืืฃ ืืืืฉืื ืืช ืกืคืจืืืช ืืกืืื ืื ืฉื openai ืืื zod ืขื:
npm install @openai/agents 'zod@<=3.25.67'
ืฉืืื ืื ืฉื ืืื ืืืชืืืช ืืคืืกื ืกืคืจืืืช openai-agents ืชืืืืช ืจืง ืืืืจืกื ืืฉื ื ืืืชืจ ืฉื zod ืืืื ืืฉ ืืฆืืื ืืืจืกื ืืงืกืืืืืช ืืืชืงื ื. ืื ื ืืงืืื ืฉืืงืจืื ืื ืืชืงื ื ืืช ืื.1 419
ืฉืืจื ืืช ืื ืืงืืฆืื ืืคืจืืืงื ืืฆืืื ืืชืืงืืื ืืืคืขืืื ืืช ืืชืืื ืืช. ืืืืื ืฉืืชื ืืฆืืืืื ืืืืจ ืขื ืืกืืื. ืืืืจ ืืื ืืืืืคื ืืืื ืืชืจืื ืฉืืชื ืืฆืืืืื ืื ืื ืฉืืื ืื ืขื ืืืืืื ื ืืกืคืื.
ืืกืืื ืคืชืื ืืช ืืกื ืืื ืืคืืชืื ืืืคืืคื ืืืื Network. ืืกืชืืื ืขื ืืืืืข ืฉืขืืืจ ืืจืฉืช ืืื ืืฉืจืช ืืืงืื ืืืื ืืืจืืช ืืืืงื ืื ื Chat.
ืืฉืื: ืื ืงืืจื ืืฉืืื ืืฉืืจืขื ื ืื ืืช ืืขืืื? ื ืกื ืืืฉืื ืขื ืจืขืืื ืืช ืืื ืืฉืืืจ ืขื ืืืืจืื ืคืขืืื ืื ืืืจื ืจืืขื ืื.
1 419
margin: 0 auto;
padding: 20px;
min-height: 100vh;
display: flex;
flex-direction: column;
}
header {
text-align: center;
margin-bottom: 30px;
color: white;
}
header h1 {
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
header p {
font-size: 1.1em;
opacity: 0.9;
}
.agent-config {
background: white;
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.config-row {
margin-bottom: 15px;
}
.config-row:last-child {
margin-bottom: 0;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #555;
}
input, textarea {
width: 100%;
padding: 12px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.3s ease;
resize: vertical;
}
input:focus, textarea:focus {
outline: none;
border-color: #667eea;
}
.chat-container {
flex: 1;
display: flex;
flex-direction: column;
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.chat-messages {
flex: 1;
padding: 20px;
overflow-y: auto;
max-height: 400px;
min-height: 300px;
}
.message {
margin-bottom: 15px;
padding: 12px 16px;
border-radius: 12px;
max-width: 80%;
word-wrap: break-word;
}
.user-message {
background: #667eea;
color: white;
margin-left: auto;
border-bottom-right-radius: 4px;
}
.assistant-message {
background: #f1f3f5;
color: #333;
border-bottom-left-radius: 4px;
}
.system-message {
background: #e3f2fd;
color: #1976d2;
text-align: center;
border-radius: 8px;
padding: 10px;
font-style: italic;
margin: 10px auto;
max-width: 90%;
}
.streaming-message {
background: #f8f9fa;
color: #333;
border-bottom-left-radius: 4px;
border-left: 3px solid #667eea;
}
.chat-input-container {
padding: 20px;
border-top: 1px solid #e1e5e9;
background: #fafafa;
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 10px;
}
* message-input { *
flex: 1;
min-height: 60px;
resize: none;
}
button {
background: #667eea;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
min-width: 80px;
}
button:hover:not(:disabled) {
background: #5a6fd8;
transform: translateY(-1px);
}
button:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
}
.status {
font-size: 12px;
color: #666;
text-align: center;
}
.status.connecting {
color: #ff9800;
}
.status.streaming {
color: #4caf50;
}
.status.error {
color: #f44336;
}
/* Typing indicator */
.typing-indicator {
display: inline-block;
padding: 8px 12px;
background: #f1f3f5;
border-radius: 12px;
margin-bottom: 15px;
}
.typing-indicator::after {
content: 'โโโ';
animation: typing 1.4s infinite;
color: #999;
}
@keyframes typing {
0%, 60% {
opacity: 1;
}
30% {
opacity: 0.3;
}
}
/* Scrollbar styling */
.chat-messages::-webkit-scrollbar {
width: 6px;
}
.chat-messages::-webkit-scrollbar-track {
background: #f1f1f1;
}
.chat-messages::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
.chat-messages::-webkit-scrollbar-thumb:hover {
background: #999;
}
/* Responsive design */
@media (max-width: 600px) {
.container {
padding: 10px;
}
header h1 {
font-size: 2em;
}
.message {
max-width: 95%;
}
.input-group {
flex-direction: column;
}
button {
align-self: flex-end;
min-width: 100px;
}
}
ืขืืฉืื ืืชื1 419
console.warn('Failed to parse JSON:', line, e);
}
}
}
}
} finally {
reader.releaseLock();
this.finalizeStreamingMessage();
}
}
handleStreamEvent(data) {
switch (data.type) {
case 'start':
console.log('Stream started:', data.message);
break;
case 'token':
if (data.content) {
this.appendToStreamingMessage(data.content);
}
break;
case 'message':
if (data.content) {
this.appendToStreamingMessage(data.content);
}
break;
case 'agent_update':
console.log('Agent updated:', data.agent_name);
break;
case 'tool_call':
this.appendToStreamingMessage('\n[Tool called]');
break;
case 'tool_output':
this.appendToStreamingMessage(\\n[Tool output: ${data.content}]\);
break;
case 'complete':
console.log('Stream completed');
this.status.textContent = 'Response complete';
break;
default:
console.log('Unknown event type:', data);
}
}
createStreamingMessage() {
const messageDiv = document.createElement('div');
messageDiv.className = 'message streaming-message';
messageDiv.innerHTML = '<span class="typing-indicator"></span>';
this.chatMessages.appendChild(messageDiv);
this.scrollToBottom();
return messageDiv;
}
appendToStreamingMessage(content) {
if (!this.currentStreamingMessage) return;
// Remove typing indicator if it exists
const typingIndicator = this.currentStreamingMessage.querySelector('.typing-indicator');
if (typingIndicator) {
typingIndicator.remove();
}
// Append the content
this.currentStreamingMessage.textContent += content;
this.scrollToBottom();
}
finalizeStreamingMessage() {
if (!this.currentStreamingMessage) return;
// Remove typing indicator
const typingIndicator = this.currentStreamingMessage.querySelector('.typing-indicator');
if (typingIndicator) {
typingIndicator.remove();
}
// Change class to final assistant message
this.currentStreamingMessage.className = 'message assistant-message';
// If the message is empty, add a default message
if (!this.currentStreamingMessage.textContent.trim()) {
this.currentStreamingMessage.textContent = 'No response received.';
}
this.currentStreamingMessage = null;
this.scrollToBottom();
}
addMessage(content, type) {
const messageDiv = document.createElement('div');
messageDiv.className = \message ${type}-message\;
messageDiv.textContent = content;
this.chatMessages.appendChild(messageDiv);
this.scrollToBottom();
}
scrollToBottom() {
this.chatMessages.scrollTop = this.chatMessages.scrollHeight;
}
}
// Initialize the chat when the page loads
document.addEventListener('DOMContentLoaded', () => {
new ChatAgent();
});
ืืืื ืืฉ ืื ืงืืืฅ CSS ืฉื ืงืจื client/style.css ืขื ืืชืืื ืืื:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
}
.container {
max-width: 800px;1 419
// Enter key in message input (Shift+Enter for new line)
this.messageInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
this.sendMessage();
}
});
// Enable send button when there's content
this.messageInput.addEventListener('input', () => {
const hasContent = this.messageInput.value.trim().length > 0;
this.sendButton.disabled = !hasContent || this.isStreaming;
});
// Auto-resize message input
this.messageInput.addEventListener('input', () => {
this.messageInput.style.height = 'auto';
this.messageInput.style.height = this.messageInput.scrollHeight + 'px';
});
}
enableInterface() {
this.messageInput.disabled = false;
this.sendButton.disabled = true;
this.status.textContent = 'Ready to chat';
this.status.className = 'status';
}
disableInterface() {
this.messageInput.disabled = true;
this.sendButton.disabled = true;
}
async sendMessage() {
const message = this.messageInput.value.trim();
if (!message || this.isStreaming) return;
const agentName = this.agentName.value.trim() || 'Assistant';
const agentInstructions = this.agentInstructions.value.trim() || 'You are a helpful assistant.';
// Add user message to chat
this.addMessage(message, 'user');
// Clear input and disable interface
this.messageInput.value = '';
this.messageInput.style.height = 'auto';
this.disableInterface();
// Set streaming status
this.isStreaming = true;
this.status.textContent = 'Connecting...';
this.status.className = 'status connecting';
try {
// Make the streaming request
const response = await fetch('/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
agent_name: agentName,
agent_instructions: agentInstructions
})
});
if (!response.ok) {
throw new Error(\HTTP error! status: ${response.status}\);
}
// Process the streaming response
await this.processStreamingResponse(response);
} catch (error) {
console.error('Error:', error);
this.addMessage('Sorry, there was an error processing your request.', 'system');
this.status.textContent = 'Error occurred';
this.status.className = 'status error';
} finally {
this.isStreaming = false;
this.enableInterface();
}
}
async processStreamingResponse(response) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
this.status.textContent = 'Streaming response...';
this.status.className = 'status streaming';
// Initialize streaming message container
this.currentStreamingMessage = this.createStreamingMessage();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Decode the chunk
const chunk = decoder.decode(value, { stream: true });
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6));
this.handleStreamEvent(data);
} catch (e) {1 419
ืืขืืงืจ ืืงืื ื ืืฆื ืืงืืืฅ ื JavaScript. ืงืืืฅ ืื ืฆืจืื ืืืคื ืืชืืืื ืืืืืจืืช ืืืขืืื ืืช ืจืฉืืืช ืืืืืขืืช ืื ืคืขื ืฉืืชืงืืืื ืืืงื ืื ืืืฉืื ืืืฉืจืช. ืืงืื ืืืจืืื ืฉื ืืื:
async processStreamingResponse(response) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
this.status.textContent = 'Streaming response...';
this.status.className = 'status streaming';
// Initialize streaming message container
this.currentStreamingMessage = this.createStreamingMessage();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Decode the chunk
const chunk = decoder.decode(value, { stream: true });
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6));
this.handleStreamEvent(data);
} catch (e) {
console.warn('Failed to parse JSON:', line, e);
}
}
}
}
} finally {
reader.releaseLock();
this.finalizeStreamingMessage();
}
}
handleStreamEvent(data) {
switch (data.type) {
case 'start':
console.log('Stream started:', data.message);
break;
case 'token':
if (data.content) {
this.appendToStreamingMessage(data.content);
}
break;
case 'message':
if (data.content) {
this.appendToStreamingMessage(data.content);
}
break;
case 'agent_update':
console.log('Agent updated:', data.agent_name);
break;
case 'tool_call':
this.appendToStreamingMessage('\n[Tool called]');
break;
case 'tool_output':
this.appendToStreamingMessage(\\n[Tool output: ${data.content}]\);
break;
case 'complete':
console.log('Stream completed');
this.status.textContent = 'Response complete';
break;
default:
console.log('Unknown event type:', data);
}
}
ื ืฉืื ืื ืฉืืงืื ืืชืืื ืืงืื ืืืืจืื ืฉืืชืืชื ืืคืืืชืื. ืืคืืืชืื ืืื ืื ืคืงืืืืช ืืื:
yield f"data: {json.dumps({'type': 'tool_call', 'message': 'Tool was called'})}\n\n"
ืืื ืืืืจืื ืืืจืืข ืฉื tool call, ืืื ื JavaScript ืื ืื ื ืืกืชืืืื ืขื ื data.type ืืืคื ืื ืืืืืืื ืืื ืืืคื ืืืืืขื:
switch (data.type) {
ืงืืืฅ ื JavaScript ืืืื ืืืืืื ืืื:
// file: client/script.js
class ChatAgent {
constructor() {
this.chatMessages = document.getElementById('chat-messages');
this.messageInput = document.getElementById('message-input');
this.sendButton = document.getElementById('send-button');
this.status = document.getElementById('status');
this.agentName = document.getElementById('agent-name');
this.agentInstructions = document.getElementById('agent-instructions');
this.isStreaming = false;
this.currentStreamingMessage = null;
this.initializeEventListeners();
this.enableInterface();
}
initializeEventListeners() {
// Send button click
this.sendButton.addEventListener('click', () => this.sendMessage());1 419
@app.post("/chat")
async def chat(request: ChatRequest):
async def generate():
agent = Agent(
name=request.agent_name,
instructions=request.agent_instructions,
)
result = Runner.run_streamed(
agent,
input=request.message,
)
# Send initial message to indicate start
yield f"data: {json.dumps({'type': 'start', 'message': 'Starting chat...'})}\n\n"
async for event in result.stream_events():
# Handle different event types
if event.type == "raw_response_event":
if isinstance(event.data, ResponseTextDeltaEvent):
# Stream individual tokens
token = event.data.delta
if token:
yield f"data: {json.dumps({'type': 'token', 'content': token})}\n\n"
elif event.type == "agent_updated_stream_event":
yield f"data: {json.dumps({'type': 'agent_update', 'agent_name': event.new_agent.name})}\n\n"
elif event.type == "run_item_stream_event":
if event.item.type == "tool_call_item":
yield f"data: {json.dumps({'type': 'tool_call', 'message': 'Tool was called'})}\n\n"
elif event.item.type == "tool_call_output_item":
yield f"data: {json.dumps({'type': 'tool_output', 'content': str(event.item.output)})}\n\n"
elif event.item.type == "message_output_item":
message_text = ItemHelpers.text_message_output(event.item)
yield f"data: {json.dumps({'type': 'message', 'content': message_text})}\n\n"
# Send completion signal
yield f"data: {json.dumps({'type': 'complete'})}\n\n"
return StreamingResponse(
generate(),
media_type="text/plain",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
}
)
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='0.0.0.0', port=8080)
ืงืื ืฆื ืืงืื
ืืฆื ืืืงืื ืื ื ืืืืืจ ืงืืืฅ HTML ืขื ืืืืจ ืืืืืขืืช ืืืืคืก ืืฉืืืืช ืืืืขื ืืืฉื:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat Agent</title>
<link rel="stylesheet" href="client/style.css">
</head>
<body>
<div class="container">
<header>
<h1>๐ค Chat Agent</h1>
<p>Powered by Lean Agents SDK</p>
</header>
<div class="agent-config">
<div class="config-row">
<label for="agent-name">Agent Name:</label>
<input type="text" id="agent-name" value="Assistant" placeholder="Enter agent name">
</div>
<div class="config-row">
<label for="agent-instructions">Agent Instructions:</label>
<textarea id="agent-instructions" placeholder="Enter agent instructions" rows="2">You are a helpful assistant.</textarea>
</div>
</div>
<div class="chat-container">
<div class="chat-messages" id="chat-messages">
<div class="system-message">
Welcome! Configure your agent above and start chatting.
</div>
</div>
<div class="chat-input-container">
<div class="input-group">
<textarea
id="message-input"
placeholder="Type your message here..."
rows="3"
disabled
></textarea>
<button id="send-button" disabled>Send</button>
</div>
<div class="status" id="status">Ready to chat</div>
</div>
</div>
</div>
<script src="/client/script.js"></script>
</body>
</html>1 419
ืืื 8 - ืืืฉืง ืืื ืืกืืื
ืืืืฉืง ืฉืื ืื ื ืืื ืจืืืืื ืืจืืืช ืืขืืืื ืขื ืกืืื ืื ืืื ืืฆ'ืื ืืืคืืคื ืืืื ืืฉืื ืืืืื ืืื ืืื ืื ืื. ืืฉืืื ืืืืืื ืืืื ืืฉืชืืฉ ื fastapi ืืฆื ืืฉืจืช ืืืืืจืืช ืืืืข HTTP Streaming. ืืืื ื ืจืื ืืช ืืงืื.
ืงืื ืฆื ืฉืจืช
ืืช ืืฉืจืช ืืชืืชื ื fastapi. ืืกืืื ืืืืืจื ื fastapi ืืืงืื ืืืฉื ื flask ืืื ืืชืืืื ืืืืื ืืช ืฉื fastapi ื async. ืกืคืจืืืช OpenAI Agents SDK ืืื ืืกืื ืืจืื ืืช, ืืืืืจ ืืืืืช ืืืืจืื ืฉืื ืืชืืื ืืืื ื:
async for event in result.stream_events():
ืื ืืืืจ ืฉืืฉืืื ืืืคืขืื ืฉืืื ืขื ืกืืื ืืืงืื ืืืืื ืืช ืืืืจืื ืืช ืืืืงื ืื ืืฉืื ื ืืฆืจืื ืื ื ืฆืจืื Event Loop ืืชืืื ืืช ืฉืื, ืืืืจื ืืื ืคืฉืืื ืืงืื ืืืช ืืื ืืืฉืชืืฉ ืืคืจืืืืืืจืง ืืื ืฉืืืจ ืืืื ืืื.
ืืคืื ืงืฆืื ืืจืืฉืื ื ืืงืื ืฆื ืฉืจืช ืฆืจืืื ืืืืืช ืืืืจืช ืืื ืืคืืกืืื ืงืืืืื ืืกืืืจื:
async def generate():
agent = Agent(
name=request.agent_name,
instructions=request.agent_instructions,
)
result = Runner.run_streamed(
agent,
input=request.message,
)
# Send initial message to indicate start
yield f"data: {json.dumps({'type': 'start', 'message': 'Starting chat...'})}\n\n"
async for event in result.stream_events():
# Handle different event types
if event.type == "raw_response_event":
if isinstance(event.data, ResponseTextDeltaEvent):
# Stream individual tokens
token = event.data.delta
if token:
yield f"data: {json.dumps({'type': 'token', 'content': token})}\n\n"
elif event.type == "agent_updated_stream_event":
yield f"data: {json.dumps({'type': 'agent_update', 'agent_name': event.new_agent.name})}\n\n"
elif event.type == "run_item_stream_event":
if event.item.type == "tool_call_item":
yield f"data: {json.dumps({'type': 'tool_call', 'message': 'Tool was called'})}\n\n"
elif event.item.type == "tool_call_output_item":
yield f"data: {json.dumps({'type': 'tool_output', 'content': str(event.item.output)})}\n\n"
elif event.item.type == "message_output_item":
message_text = ItemHelpers.text_message_output(event.item)
yield f"data: {json.dumps({'type': 'message', 'content': message_text})}\n\n"
# Send completion signal
yield f"data: {json.dumps({'type': 'complete'})}\n\n"
ืืฉ ืคื ืคื ืืื ืืกืืื ืขื run_streamed ืืื ืืคืขืืช yield ืขืืืจ ืื ืืงืกื ืฉืืกืืื ืืืืฆืจ.
ืื ืฉืืฉืชืืฉ ื generate ืืื ืคืงืืืช ืืฉืืื:
@app.post("/chat")
async def chat(request: ChatRequest):
async def generate():
...
return StreamingResponse(
generate(),
media_type="text/plain",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
}
)
ืืกืคืจืืืช fastapi ืืืคืืช ืขืืืจื ืืฆืืจื ืืืืืืืืช ืืืืจืืช ืื ืืืืข ืฉืืืืข ื yield ืืืืง ืืืชืฉืืื ืืืคืืคื.
ืงืื ืฆื ืืฉืจืช ืืืื ืืงืืืฅ main.py ืืื:
import json
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse, StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from agents import Agent, ItemHelpers, Runner
from openai.types.responses import ResponseTextDeltaEvent
app = FastAPI()
* Add CORS middleware *
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
* Mount static files *
app.mount("/client", StaticFiles(directory="client"), name="client")
class ChatRequest(BaseModel):
message: str
agent_name: str = "Assistant"
agent_instructions: str = "You are a helpful assistant."
@app.get("/", response_class=HTMLResponse)
async def index():
with open("client/index.html", "r") as f:
return HTMLResponse(content=f.read())1 419
RawResponsesStreamEvent(data=ResponseCompletedEvent(response=Response(id='resp_6895b0fd4464819abe44eb9e456d2d960754fc8434302a7d', created_at=1754640637.0, error=None, incomplete_details=None, instructions='Tell me a joke', metadata={}, model='gpt-4o-2024-08-06', object='response', output=[ResponseOutputMessage(id='msg_6895b0fda330819a9278cd18b1f7a04b0754fc8434302a7d', content=[ResponseOutputText(annotations=[], text='Hi there! Ready for a joke?', type='output_text', logprobs=[])], role='assistant', status='completed', type='message')], parallel_tool_calls=True, temperature=1.0, tool_choice='auto', tools=[], top_p=1.0, background=False, max_output_tokens=None, max_tool_calls=None, previous_response_id=None, prompt=None, reasoning=Reasoning(effort=None, generate_summary=None, summary=None), service_tier='default', status='completed', text=ResponseTextConfig(format=ResponseFormatText(type='text'), verbosity='medium'), top_logprobs=0, truncation='disabled', usage=ResponseUsage(input_tokens=16, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=9, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=25), user=None, prompt_cache_key=None, safety_identifier=None, store=True), sequence_number=15, type='response.completed'), type='raw_response_event')
-- Message output:
Hi there! Ready for a joke?
=== Run complete ===
Process finished with exit code 0
ืืคืฉืจ ืืจืืืช ืืช ืื ืืืืงื ืื ืืืืคืกืื ืืืื ืฉืื ืืืืฆืจืื, ืืืืจืืื ืืืืขืช ืกืืื ืขื ืืืืืขื ืืืืื. ืืชืืื ืืืช ืืืืชืืืช ื ืจืฆื ืืืคื ืืฆืืจื ืฉืื ื ืืื ืกืื ืืืืขื, ืืืืืื:
1. ืืืืขืืช raw_response_event ืืืฉืืื ืืืืืฉ ืืืื ืฉืืื ืืืชืื ืืชืฉืืืช ืืืืื ืืื ืืืจืืืช ืืช ืืชืฉืืื ืืืื ืฉืืื ื ืืฆืจืช.
2. ืืืืขืืช tool_call_item ืืฆืืื ืืืฉืชืืฉ ืกืืื ืืืืื ืืืืฉืง ืฉืืืืจ ืฉืืืืื ืขืืฉืื ืืคืขืื ืืื, ืืืฉื ืืืคืฉ ืืืื ืืจื ื.
3. ืืืืขืืช message_output_item ืืขืืื ื ืืช ืืืืืขื ืฉืืืคืืขื ืืืืื ืืฉืืื ืขื ืืืงืกื ืืืื ืฉื ืืืืืขื. ืืคืฉืจ ืื ืืืฉืชืืฉ ืืืืจืืข ืื ืืื ืืฉืืืจ ื DB ืืช ืืืืืขื.
ืขืืฉืื ืืชื
ืืืกืืคื ืืชืืื ืืช ืฉืื ื Tool ืืืฉืื, ืืืฉื ืคืื ืงืฆืื ืฉืืืืืจื ืืฆืืจื ืืงืจืืืช ื ืืฉื ืืืืืื. ืืืืื ืฉืืืืื ืืคืขืื ืืช ื Tool ืืฉืืื ืื ืืืืืขืืช ืฉืืชืงืืืืช.
ืืคืืกืืื ืืืืื ื ืจืื ืืื ืืืืจืื ืืช ืชืฉืืืืช ืืืืื ืืืืฉืงื ืืื, ืืืื ืืืืืจื ืืื ืืืงืื MCP.1 419
RawResponsesStreamEvent(data=ResponseCreatedEvent(response=Response(id='resp_6895b0fd4464819abe44eb9e456d2d960754fc8434302a7d', created_at=1754640637.0, error=None, incomplete_details=None, instructions='Tell me a joke', metadata={}, model='gpt-4o-2024-08-06', object='response', output=[], parallel_tool_calls=True, temperature=1.0, tool_choice='auto', tools=[], top_p=1.0, background=False, max_output_tokens=None, max_tool_calls=None, previous_response_id=None, prompt=None, reasoning=Reasoning(effort=None, generate_summary=None, summary=None), service_tier='auto', status='in_progress', text=ResponseTextConfig(format=ResponseFormatText(type='text'), verbosity='medium'), top_logprobs=0, truncation='disabled', usage=None, user=None, prompt_cache_key=None, safety_identifier=None, store=True), sequence_number=0, type='response.created'), type='raw_response_event')
RawResponsesStreamEvent(data=ResponseInProgressEvent(response=Response(id='resp_6895b0fd4464819abe44eb9e456d2d960754fc8434302a7d', created_at=1754640637.0, error=None, incomplete_details=None, instructions='Tell me a joke', metadata={}, model='gpt-4o-2024-08-06', object='response', output=[], parallel_tool_calls=True, temperature=1.0, tool_choice='auto', tools=[], top_p=1.0, background=False, max_output_tokens=None, max_tool_calls=None, previous_response_id=None, prompt=None, reasoning=Reasoning(effort=None, generate_summary=None, summary=None), service_tier='auto', status='in_progress', text=ResponseTextConfig(format=ResponseFormatText(type='text'), verbosity='medium'), top_logprobs=0, truncation='disabled', usage=None, user=None, prompt_cache_key=None, safety_identifier=None, store=True), sequence_number=1, type='response.in_progress'), type='raw_response_event')
RawResponsesStreamEvent(data=ResponseOutputItemAddedEvent(item=ResponseOutputMessage(id='msg_6895b0fda330819a9278cd18b1f7a04b0754fc8434302a7d', content=[], role='assistant', status='in_progress', type='message'), output_index=0, sequence_number=2, type='response.output_item.added'), type='raw_response_event')
RawResponsesStreamEvent(data=ResponseContentPartAddedEvent(content_index=0, item_id='msg_6895b0fda330819a9278cd18b1f7a04b0754fc8434302a7d', output_index=0, part=ResponseOutputText(annotations=[], text='', type='output_text', logprobs=[]), sequence_number=3, type='response.content_part.added'), type='raw_response_event')
[Token]: Hi
[Token]: there
[Token]: !
[Token]: Ready
[Token]: for
[Token]: a
[Token]: joke
[Token]: ?
RawResponsesStreamEvent(data=ResponseTextDoneEvent(content_index=0, item_id='msg_6895b0fda330819a9278cd18b1f7a04b0754fc8434302a7d', logprobs=[], output_index=0, sequence_number=12, text='Hi there! Ready for a joke?', type='response.output_text.done'), type='raw_response_event')
RawResponsesStreamEvent(data=ResponseContentPartDoneEvent(content_index=0, item_id='msg_6895b0fda330819a9278cd18b1f7a04b0754fc8434302a7d', output_index=0, part=ResponseOutputText(annotations=[], text='Hi there! Ready for a joke?', type='output_text', logprobs=[]), sequence_number=13, type='response.content_part.done'), type='raw_response_event')
RawResponsesStreamEvent(data=ResponseOutputItemDoneEvent(item=ResponseOutputMessage(id='msg_6895b0fda330819a9278cd18b1f7a04b0754fc8434302a7d', content=[ResponseOutputText(annotations=[], text='Hi there! Ready for a joke?', type='output_text', logprobs=[])], role='assistant', status='completed', type='message'), output_index=0, sequence_number=14, type='response.output_item.done'), type='raw_response_event')1 419
ืืื 7 - ืืืจืืช ืชืฉืืืืช
ืืื ืืืืคืืื ืื ืืืฉืืืื ืืืืืฉืื ืฉื ืืขืจืืืช ืื'ื ืืืืช ืืื ืืฉืืืืฉ ื Streaming. ืืืืืื ืฉื ืืืืื ืฉืคื ืืืืืื ืืื ืฉืื ืืืืฆืจืื ืืืื ืคืื ืืื ืืื. ืืืขืจืืช ืืื ืืจืงืืืืืช ืื ืืืืจ ืฉืืฉืชืืฉืื ืฆืจืืืื ืืืืืช ืืืื ืืื ืขื ืฉืืืืืื ืืืชืื ืืช ืืืืืขื ืืืื ืืืืืฉืื ืืช ืืฉืืื. ืืคืืื ืืชืืืืืื ืืกืื ืืจืื ืืื ืื ืืืืจ ืฉืืืฉืชืืฉืื ืงืฉื ืืืืื ืืืคื ืืืืืง ืื ืื ื ืืชืืืื.
ืืคืืชืจืื ืฉื ืกืคืงื ืืืืืืื ืืื ืืืฆืืจ APIs ืฉืชืืืืื ืืืืจืืช ืืืืข ืืืฉืืื ืืช ืืืงืกื ืืืืืื ืืื ืืื ืฉืืื ื ืืฆืจ, ืืืื ืืืจื ืืืื. ืืชืืฆืื ืืื ืืืืืช ื Streaming ืฉืื ืื ื ืืืืจืื ืืืชืจื ื Chat - ืื ืื ื ืืืื ื ืืืืื ืฉืืืืื ืืกืืื ืืืชืื ืืช ืื ืืคืื, ืืื ืืคืืืช ืืืืื ืืืืชื ื ืื ืื ื ืืืืืื ืืจืืืช ืืช ืืชืืฆืื ื ืื ืืช ืืื ืืขืื ืืื.
ืกืืื ืื ืฉืื ืื ื ืืื ืื ืืจืื ืืฆืืจืื ืืชืช ืืืืืช ืืฉืชืืฉ ืืืื ืืืื ืื ืกืคืจืืืช ืขืืืื ืขื ืกืืื ืื ืืืืืช ืืชืช ืคืืชืจืื ืื ืืืืจืืช ืืืืืข. ืืคืืกื ืื ื ืจืื ืืช ืืคืืชืจืื ืฉื OpenAI Agents SDK.
ืืืืืช ืืืจืืช ืืงืกื ืคืฉืืื ืืฉืืจืช ืืคืงืืื
ืืฉืืื ืืืืงืืช ืืืฉืืงืื ื ืชื ื ืื ื ื Agents SDK ืืืืืช ืืืจืืช ืืงืกื ืคืฉืืื ืฉืืคืฉืจ ืืืจืืฅ ืืฉืืจืช ืืคืงืืื. ืื ืืงืื:
import asyncio
from agents import Agent, run_demo_loop
async def main() -> None:
agent = Agent(name="Assistant", instructions="You are a helpful assistant.")
await run_demo_loop(agent)
if __name__ == "__main__":
asyncio.run(main())
ืืืืื ืื ืืฉืืฉืช ืืืืืงืช ืกืืื ืฉืขืืื ืืชืื Session ืืืืฆืขืช:
1. ืงืจืืืช ืืืืขื ืืืืฉืชืืฉ.
2. ืฉืืืจืช ืืืืืขื ืืืืืจืื ืืืขืืจืชื ืืกืืื.
3. ืืฆืืช ืืคืื ืืืกืืื ื Streaming, ืื ืฉืืืื ืืืฆื.
4. ืงืจืืืช ืืืืขื ื ืืกืคืช ืืืืฉื ืฉืืื, ืืืืืจ ืฉืืืืชื ืืกืืื ืืฆืืจืืฃ ืื ืืืืืขืืช ืืงืืืืืช.
ื ืกื ืืืคืขืื ืืช ืืืืืื ืืฆืืื ืืืืืจ ืขื ืกืืื ืฉื OpenAI ืื ืกืคืง ืืืจ ืืจื LiteLLM.
ืืืจืืช ืืืืข ืืงืื ืฉืื ื
ืืืืื ืฉืืงืื ืฉืื ื ืื ืื ื ื ืขืืืฃ ืืฉืืื ืืืืืื, ืืืืืขืืช ืื Sessions ืืื ืื ื ืจืฆื ืฉืืคืื ืชืืื ืืืฆื ืืืกื ืืืื ื ืฉืชืืฉ ืืืืืื ืืืื ืจืง ืืืืืงืืช ืืืงืื ืืืืชื ื ืฉืชืืฉ ืืคืื ืงืฆืื Runner.run_streamed ืืื ืืืจืืฅ ืกืืื ืืืงืื ืืื ื ืืืืขืืช ืืืืจืื.
ืื ืืืืขื ืฉืืชืงืืืช ืืืกืืื ืืืืขื ืขื type. ืกืื ืืืืืขื ืืืกืืกื ืืื raw_response_event ืืืื ืืืืืขืืช ืฉืืขืืืจืืช ืืช ืืืืืื ืฉืืืืื ืืืืฆืจ. ืกืืื ืืืืขืืช ื ืืกืคืื ืืืืืื ืืืืื ืืชื ืืืืื ืจืืฆื ืืืคืขืื ืืื, ืืชื ืืืืื ืกืืื ืืืืขื ืฉืืื ืืืชื ืงืืืื ื ืชืืฆืื ืฉื ืืื. ืืืืืื ืืืื ืืืคืืกื ืืช ืื ืืืืืขืืช:
import asyncio
import random
from agents import Agent, ItemHelpers, Runner, function_tool
from openai.types.responses import ResponseTextDeltaEvent
async def main():
agent = Agent(
name="Joker",
instructions="Tell me a joke",
)
result = Runner.run_streamed(
agent,
input="Hello",
)
print("=== Run starting ===")
async for event in result.stream_events():
# We'll ignore the raw responses event deltas
if event.type == "raw_response_event":
if isinstance(event.data, ResponseTextDeltaEvent):
print(f"[Token]: {event.data.delta}")
else:
print(event)
# When the agent updates, print that
elif event.type == "agent_updated_stream_event":
print(f"Agent updated: {event.new_agent.name}")
continue
# When items are generated, print them
elif event.type == "run_item_stream_event":
if event.item.type == "tool_call_item":
print("-- Tool was called")
elif event.item.type == "tool_call_output_item":
print(f"-- Tool output: {event.item.output}")
elif event.item.type == "message_output_item":
print(f"-- Message output:\n {ItemHelpers.text_message_output(event.item)}")
else:
print(f" -- Other Event: {event}")
print("=== Run complete ===")
if __name__ == "__main__":
asyncio.run(main())
ืืจืฆืช ืืชืืื ืืช ืืืคืืกื ืืช ืืคืื ืืื:
/Users/ynonp/work/projects/ai/leanagentssdk/.venv/bin/python /Users/ynonp/work/projects/ai/leanagentssdk/streaming.py
=== Run starting ===
Agent updated: Joker1 419
ืืื 6 - ืืจืืื ืืงืื ืืืืืจืช ืืืืืื
ืืคืืกื ืืืื ืืกืืื ืืช ืืืืง ืืจืืฉืื ืฉื ืกืืืจืช ืืคืืกืืื ืขื ืคืืชืื ืืฉืืื AI. ืืกืืืจื ืขื ืขืืฉืื ืืืื ื ืืื ืืืชืงืื ืืช ืกืคืจืืืช OpenAI Agents SDK, ืืืื ื ืขื ืฉื ื ืกืืื ืืขืจืืืช ืืฉืืืืืช AI (ืกืงืจืืคื ืฉืจืฅ ืืจืงืข ืืกืืื ืืื ืืจืงืืืื) ืืื ืื ื ืืคืืื ืืืจ ืืืืขืื ืืื ืืืชืื ืชืืื ืืืช ืคืฉืืืืช ืืฉื ื ืืกืืืื.
ืืืื ื ืกืืื ืืช ืืืืง ืืจืืฉืื ืืกืงืืจื ืฉื ืืื ื ืืงืื ืืจืฆืื ืืืขืจืืช ืืืื ืืืคืื ืขื ืืืืจืช ืืืืืื.
ืืื ื ืงืื
ื ืืืืจ ืืื ืืชืื ื ืกืืื ืืชืืื ืืืช ืืืืืื ืขื ืขืืฉืื:
market_research_agent = Agent(
name="MarketResearcher",
model=LitellmModel(model="github/gpt-4.1", api_key=os.environ["GITHUB_TOKEN"]),
output_type=list[BlogPostIdea],
instructions="""
You are a market researcher and your job is to suggest cool ideas for blog posts.
I will send you ideas and you will help me turn them into engaging posts,
Or I will send you topics and you will help to focus me on the best viral ideas in these niches.
"""
)
ืืืขืจืืช ืืืืชืืช ืืฉ ืฉื ื ืืืจืื ืฉืืืื ืืจืื ืืืชืจ ืืกืืืืื ืืืฉืจ ืืืืืื: ืืืืจืช ืืืืื ืืืืืจืช ืืืืง ื instructions. ืคืจืืืคื ืืื ืืกืืืจ ืืขืืืง ืื ืชืคืงืื ืืืืื, ื ืืชื ืื ืงืื ืืงืกื ืืชืื ืืขืืื ืฉืืื ืืืื ืืฉืื ืืืื ืืืืืืืช ืืงืื ืืคืื. ืคืจืืืคื ืืื ืื ืฆืจืื ืืืชืืื ืืืืื, ืืืื ืฉืื ืื ืืืืื ืืืืื ืืจืื ืคืขืืื ืื ืฉืื ืื ืื ืืกืื ืฉื ืืคืจืืืคื, ืืืคืขืืื ืืืจืกื ืืืฉื ืฉื ืืืืื ืฉืืคืืื ืื ืืืงืฉืชื ืคืชืืื ืืืจืืช ืืืืชื ืคืจืืืคื ืืขืืื ืืืชืจ ืืื ืื ืคืืืช ืืื.
ืืืื ืืืชืืืก ืืคืจืืืคืืื ืืชืืจ ืืืง ืขืฆืืื ืืืงืื ืืืื ืื ื ืืืื ืืฉืืืจ ืคืจืืืคื ืืงืืืฅ ื ืคืจื. ืืจืื ืคืขืืื ืื ื ืื ืืืื ืืฉืชืื ืืฉืชื ืื ืืชืื ืืคืจืืืคื ืืื ืื ื ืืืื ืืฉื ืืช "ืคืจืืืจืื" ืืกืืื ืฉืื ืืืชืื ืื ืกืืืืช. ืืื ืืคืจืืืงื ืืืืชื ืชืืื ืื ื ืชืืงืื ืืฉื agents, ืืชืืื ืชืืงืืื ืืื ืกืืื ืืืชืืื ืงืืืฅ ืกืืื ืืงืืืฅ ืืืจืืืช:
agents/
โโโ researcher/
โ โโโ agent.py
โ โโโ prompt.md
ืืฉืืื ืืฉืื ืืฉืชื ืื ืืืื ืืืฉืชืืฉ ืืกืคืจืืืช jinja2 ืืื ืงืื ืืกืืื ืืืื:
from agents import Agent, Runner
from pydantic import BaseModel, Field
from jinja2 import Environment, FileSystemLoader
class BlogPostIdea(BaseModel):
title: str = Field(..., title="Title", description="The title of the blog post"),
main_concepts: list[str] = Field(..., title="Main Concepts", description="Main concepts for the post")
env = Environment(loader=FileSystemLoader("agents/researcher"))
template = env.get_template("instructions.md")
market_research_agent = Agent(
name="MarketResearcher",
output_type=list[BlogPostIdea],
instructions=template.render()
)
ืืืืืื
ืืฉ ืืืื ืืืืืื ืืื ืืืื ืืืชืงืืข ืขื ืืืื ืืื ืฉ"ืชืืื ืขืืื". ืืคืขืืื ืืฉืื ืื ื ืืงืื ืชืืฆืื ืืืจ, ืืฉ ืืฉืืืืช ืคืฉืืืืช ืฉืืื ืืฉืื ืขืืืื ืืจืื ืืืฉ ืื ืืฆืืื ืฉืืืืืืื ืืคืฉืืืื ืืชื ื ืชืืฆืื ืืืชืจ ื ืืื ื ืืืืื Reasoning ืืชืงืื. ืื ืืขืจืืช ืืื ืฉืื ื ืืืฉืื ืื ืกืืช ืืคืชืืจ ืืฉืืื ืขื ืืกืคืจ ืืืืืื ืืืกืคืจ ืคืจืืืคืืื ืืืขืฉืืช ืืืคืืืืืืฆืื. ืื ืืกืืจ ืฉืื ื ืืืืง ืืืื ืืืืืื ืืืื ืืขืืืจ ืื ืืื:
1. ื'ืืื ื ืคืืืฉ ืืืื ืืื, ืืืืจ ืืืื. ืื ืืื ืืฆืืื ืืคืชืืจ ืืช ืืืขืื ืฉืืื ืืจืืืืชื.
2. ืืืื Deepseek ืืกืื ื ืื ืืืื ืืื ืืืืืจ. ืฉืืื ืื ืกืืช ืื ืืช ืืืจืกืช ื Chat ืืื ืืช ืืืจืกืช ื Reasoning ืฉืืื.
3. ืงืืื ืืงืจ ืืื ืงืืื ืกืื ื ืืืืจ. ืืืฉืืืืช ืชืจืืื ืื ืืฉืืืืช ืฉืืืจืฉืืช ืืฆืืจืชืืืช ืืคืฉืจ ืืงืื ืืื ื ืชืืฆืื ืืืื ืืืคืขืืื ืื ืฉืืื ืืช ืืืืืจ.
4. ืืืืื ื Reasoning ืืืคืืจืกืืื (ื'ืืื ื ืคืจื, o3, ืืืคืืก) ืืืื ืืงืจืื ืืืืืืื. ืืืื ืืืฉืชืืฉ ืืื ื Workflows ืฉืจืฆืื ืืจืงืข ืืื ืื ืจืง ืืืืง ืงืื ืืืชืืืื.
5. ืืคืฉืจ ืืงืื ืืืฉื ืืืืืื ืงืื ืคืชืื ืืจื https://openrouter.ai/models.
ืืืื ืื ืกืืช ืืกืคืจ ืืืืืื ืืื ืืืืืจ ืืช ืืจืืฉืื ืฉืขืืื, ืืืื ืื ืกืืช ืขื ืืกืคืจ ืคืจืืืคืืื ืืืื ืคืขื ืืืื ืืืืืจ ืขื ืื ืืกืื ืื ืืืจืื ืืฉืชื ืื. ืืฉ ืื ืืขืจืืืช Tracing ืฉืืืคืฉืจืืช ืื ืืจ ืื ืืงืฉื ืฉื ืฉืืืช ื AI ืืื ืชืฉืืื ืฉืื ืื ืจืื ืืืืฉื ืืกืืืจื ืืื ืืฉืื ืืืชื.
ืขืืฉืื ืืชื
ืืืจืฉืื ื OpenRouter, ืืฉืงืืขื 2$ ืืงืจืืืืื ืืฉืืื ืืฉืืื ืืืกืคืจ ืืืืื ืงืื ืคืชืื ืืื ืืจืืืช ืืช ืืืืื ืืื ืืชืฉืืืืช ืืื ื ืืชื ืืื ืืช ืืชืฉืืื ืืืืื ืืืืชืจ. ืืืืจ ืืื ืืฉืชืืฉื ืืืฃ ืืชืืขืื ืืื:
https://docs.litellm.ai/docs/providers/openrouter
ืืื ืืืืจ ืืช OpenRouter ืืงืื ืกืืื ืฉืชืืชืื ืขื OpenAI Agents SDK ืืชื ื ืืืืื ืงืื ืคืชืื ืืืฆืข ืืช ืืืฉืืืืช.1 419
[{'role': 'user', 'content': 'What shells are installed?'}, {'arguments': '{}', 'call_id': 'call_LLe5SmhcYkLyouuo9lGwkgch', 'name': 'read_shells_file', 'type': 'function_call', 'id': 'fc_688e2ba2fe94819b990373d3ad78a90709782c5a467ec704', 'status': 'completed'}, {'call_id': 'call_LLe5SmhcYkLyouuo9lGwkgch', 'output': '# List of acceptable shells for chpass(1).\n# Ftpd will not allow users to connect who are not using\n# one of these shells.\n\n/bin/bash\n/bin/csh\n/bin/dash\n/bin/ksh\n/bin/sh\n/bin/tcsh\n/bin/zsh\n/usr/local/bin/pwsh\n/usr/local/bin/bash\n/usr/local/bin/zsh\n', 'type': 'function_call_output'}, {'id': 'msg_688e2ba416c4819b94d498d53c029cbd09782c5a467ec704', 'content': [{'annotations': [], 'text': 'The installed shells listed in the \/etc/shells\ file are:\n\n1. \/bin/bash\\n2. \/bin/csh\\n3. \/bin/dash\\n4. \/bin/ksh\\n5. \/bin/sh\\n6. \/bin/tcsh\\n7. \/bin/zsh\\n8. \/usr/local/bin/pwsh\\n9. \/usr/local/bin/bash\\n10. \/usr/local/bin/zsh\', 'type': 'output_text', 'logprobs': []}], 'role': 'assistant', 'status': 'completed', 'type': 'message'}]
The installed shells listed in the \/etc/shells\ file are:
1. \/bin/bash\
2. \/bin/csh\
3. \/bin/dash\
4. \/bin/ksh\
5. \/bin/sh\
6. \/bin/tcsh\
7. \/bin/zsh\
8. \/usr/local/bin/pwsh\
9. \/usr/local/bin/bash\
10. \/usr/local/bin/zsh\
Process finished with exit code 0
ืชืืืื ืื ื ืจืืื ืืช ืฉืืจืช ืืืืคืกื Tool Call ืฉืืืืืจื ืื ืฉืืคืื ืงืฆืื ืฉืื ื ืงืจืื. ืืืจ ืื ืืืืคืกืช ืจืฉืืืช ืื ืืืืืขืืช ืฉืืืืืจื ืื ืื ืงืจื. ืื ื ืืืื ืืืืืช ืฉื:
1. ืืืืขื ืืืืฉืชืืฉ ืขื ืืฉืืื ืฉืื.
2. ืืืืขื ืืืกืืื ืฉืืืงืฉ ืืืคืขืื ืืช ืืคืื ืงืฆืื.
3. ืืืืขื ืืืืืืืืช ืื SDK ืขื ืืชืืฆืื ืฉื ืืคืื ืงืฆืื.
4. ืืืืืขื ืืืืจืื ื ืฉื ืืกืืื ืฉืืกืืืช ืืช ืืชืฉืืื ืืฉืืื.
ืืืืฉื ืืกืืืจื ื ืจืื ืขืื ืืืืืืืช ืืืคืขืืช ืืืื ืืื ื ืืืจ ืืช ืืืืื ืืืืื ืื ื SDK. ืืื ืชืืื ืืื ืชืจืืืืื.
ืขืืฉืื ืืชื
1. ืืืกืืคื ืคืจืืืจืื ืืคืื ืงืฆืื. ื ืกื ืืชืช ืืกืืื ืืื ืฉืืืื ืืงืจืื ืื ืงืืืฅ ืขื ืืืืกืง ืฉืืื. ืืฉืื: ืืื ืืฉ ืืขืืืช ืืืืื ืืืื ืืื? ืืืื ืืืื ืื ืืืื ืืืชืื?
2. ืืขืืืจื ืืกืืื ืฉื ื ืืืื, ืืื ืฉืืืฆืจ ืงืืืฅ ืจืืง ืืืื ืฉืืืฆืจ ืชืืงืืื. ืืงืฉื ืืืกืืื ืืืฆืืจ ืชืืงืืื ืืืืงื ืฉืืื ื ืืฆืจื.
3. ืืืืืคื ืืช ืืชืืืืจ ืฉื ืฉื ื ืืกืืื ืื ืืืงืฉื ืืืกืืื ืืืฆืืจ ืชืืงืืื. ืฉืืื ืื ืฉืืคืขื ืืืคืขื ืืืื ืฉืืืฆืจ ืงืืืฅ (ืื ืืชืืืืจ ืฉืื ืืืจ ืฉืืื ืืืฆืจ ืชืืงืืื) ืื ืืฆืจ ืงืืืฅ.
4. ืืคืขืืื ืืช ืืงืื ืืื:
import asyncio
from agents import Agent, Runner, function_tool
@function_tool()
def create_empty_file(filename: str):
"""
Creates a new empty file
:param filename: the filename to check
"""
print("Tool Call: create_empty_file")
@function_tool()
def check_file_exists(filename: str) -> bool:
"""
Check if a file exists
:param filename: the filename to check
:return: True if exists
"""
print("Tool Call: check_file_exists")
return False
async def main():
agent = Agent(
name="Assistant",
tools=[create_empty_file, check_file_exists],
instructions="You are a mission critical filesystem agent. Some operations may fail. You need to verify every action worked and retry failed operations",
)
result = await Runner.run(agent, "Create an empty file named test.txt")
print(result.to_input_list())
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
ืื ืืชื ืืฆืคืื ืฉืืงืจื? ืื ืงืจื? ื ืกื ืืช ืื ืขื ืืืืืื ืฉืื ืื ืืฉืืื ืื ืื ืืืชื ืืืืช ืฉืื ื ืืื ืืื.1 419
ืืื 5 - ืฉืืืืฉ ืืืืื
ืืืืจืื ืืช ืืฉืืจื-
result = await Runner.run(agent, user_message)
ืืืืจื ื ืขื ืื ืฉืืื ืฉืืืืช ืจืฉืืืช ืืืืขืืช ืืืฉืชืืฉ ืืืืื AI, ืืื ืืขืฆื ืืืืืจ ืืืืืื - ืืืืืช ืืคืขืืช ืืืืื.
ืื ืื ืืคืขืืช ืืืื
ืื ืื ื ืืืืขืื ืืื ืืืขืืืจ ืืืืข ืืืืืคื ื AI ืืืขืจืืช ืืฉืืืืช AI - ืคืฉืื ืืืกืืคืื ืืช ืืืืืข ืืื ืืจืฉืืืช ืืืืืขืืช. ืื ืื ืฉืขืฉืื ื ืืืจ ืขื ืืืืืขื ืืืืฉืชืืฉ, ืืงื ืืจืืืช ืืื ืื ืขืืื ืขื ืืืืข ื ืืกืฃ, ืืืืืื ืชืืื ืฉื ืงืืืฅ:
async def main():
agent = Agent(
name="Assistant",
instructions="Answer questions about the file /etc/shells",
)
file_content = open('/etc/shells', 'r').read()
result = await Runner.run(agent, [
{"role": "user", "content": f"File Contents: {file_content}"},
{"role": "user", "content": "What shells are installed?"}
])
print(result.final_output)
ืืื ืื ืืืื ืืืืืื ืืืคืื? ืื ืื ืืชืฉืืื ืืฉืืื ืืืืืืช ืืชืื ืงืืืฅ ืื AI ืืฆืืื ืืืืืช ืืช ืื? ืคื ื ืื ืก ืืื ืื ืื ืฉื ืืคืขืืช ืืืื ืืืื ืขืืื ืื:
1. ืื ืื ื ืฉืืืืื ืกืืืจืช ืืืืขืืช ืืกืืื ืืืืงืฉืื ืืฉืืื. ืกืืืจืช ืืืืืขืืช ืืืืืช ืืืืขื ืฉืืคืจืืช ืจืฉืืื ืฉื "ืคืื ืงืฆืืืช" ืฉืืกืืื ืืืื ืืืงืฉ ืืืคืขืื.
2. ืืกืืื ืืืืข ืืฉืืื ืจืง ืชืฉืืื ืืืช. ืืืื ืฉืฉืืื ื ืจืฉืืื ืฉื ืคืื ืงืฆืืืช ืืชืฉืืื ืขืฉืืื ืืืืืช ืืงืฉื ืืืคืขืืช ืืืช ืื ืืืชืจ ืืคืื ืงืฆืืืช ืืื - ืืืื ืืงืฉื ืืืคืขืืช ืืืื.
3. ืืงืื ืฉืงืจื ื API ืฆืจืื ืืืืืช ืืช ืืืงืฉื, ืืืคืขืื ืืช ืืคืื ืงืฆืื ืืืคื ืืช ืฉืื ืืกืืื ืขื ืืชืฉืืื. ืืคืขื ืจืฉืืืช ืืืืืขืืช ืชืืืื ืืช ืืชืฉืืื ืืงืืืืช ืฉื ืืกืืื ืฉืืืงืฉืช ืืืคืขืื ืืื, ืืื ืืืืขื ืขื ืชืืฆืืช ืืืื.
4. ืขืืฉืื ืืกืืื ืฆืจืื ืืืืกืืฃ ืืืืขื. ืื ืืืืื ืืืืืช ืืืืขืช ืกืืืื ืขื ืชืฉืืื ืื ืืืืขื ืขื ืืงืฉื ืืืคืขืืช ืืื ื ืืกืฃ.
ืืืฆืืจืช ืืกืืื ืื ืื ื ืืืืืื ืืืืืจ ืืช ืืืื ืืืช ืืคืขืืช ืืืืื, ืขื ืืชื ืืืืฉืื ืืช ืืืืืื ืืื ืืืื ืืืื ืืืคืฉืจ ืืกืืื ืืืจืืฅ. ืืืื ื ืจืื ืืื ืื ืขืืื ืืืืฆืขืืช ืืืคืื ืืกืืจ, ืืืงืื ืฉืื ื ืืขืืืจ ืืจืืฉ ืืช ืชืืื ืืงืืืฅ ืื ื ืืชื ืืกืืื ืืช ืืืคืฉืจืืช ืืงืจืื ืืืชื.
ืืขืืจืช ืืื ืืกืืื
ืื ืกืืื ืืืืข ืืงืื ืืื ืื ืืขืจื ืฉื ืืืื. ืืื ืืื ืืกื ืืื ืคืื ืงืฆืื ืฉืืกืืื ืช ืืชืืจ "ืืื" ืืขืืจืช ืืงืืจืืืจ ืืฉื function_tool ืื SDK. ืืชืืขืื ืฉื ืืคืื ืงืฆืื ืขืืืจ ืืกืืื ืืชืืจ ืชืืืืจ ืืืื ืืื ืืกืืื ืืืืข ืืืืื ืืฆืืื ืืืคืขืื ืืช ืืืชื ืคืื ืงืฆืื.
ืงืื? ืืื:
import asyncio
from agents import Agent, Runner, function_tool
@function_tool()
def read_shells_file():
"""
Reads the file /etc/shells and returns the full content
"""
print("Tool Call: read_shells_file")
with open('/etc/shells', 'r', encoding='utf8') as f:
return f.read()
async def main():
agent = Agent(
name="Assistant",
tools=[read_shells_file],
instructions="Answer questions about the file /etc/shells",
)
result = await Runner.run(agent, "What shells are installed?")
print(result.to_input_list())
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
ืืคืื ืงืฆืื ืืืืืื ืื ืืงืืืช ืคืจืืืจืื. ืืชืืขืื ืฉืื ืืืืืจ ืืกืืื ืฉืฆืจืื ืืืคืขืื ืืืชื ืืฉืจืืฆืื ืืงืื ืืช ืืชืืื ืฉื ืืงืืืฅ /etc/shells. ืืืืจ ืืืืงืฉื ื ืืื ื ืืขื ืืช ืขื ืฉืืืืช ืขื ืืงืืืฅ ืืฉืืื ื ืฉืืื ืขื ืืงืืืฅ ืืกืืื ืืืื ืฉืืืื ืืืื ืืงืจืื ืืช ืืงืืืฅ ืืื ืฉืืืื ืืขื ืืช ืขื ืืฉืืื.
ืืฉืืคืขืืืื ืืช ืืชืืื ืืช ืืงืืืื ืืช ืืคืื ืืื:
/Users/ynonp/work/projects/ai/leanagentssdk/.venv/bin/python /Users/ynonp/work/projects/ai/leanagentssdk/explain_file.py
Tool Call: read_shells_file
Endi mavjud! Telegram Tadqiqoti 2025 โ yilning asosiy insaytlari 
