शुरुआत
गाइड: टूल-कॉलिंग एजेंट
समानांतर टूल कॉल, स्टेप लिमिट, स्ट्रक्चर्ड आउटपुट और लागत नियंत्रण के साथ एक एजेंट लूप बनाना सीखें, पूरे कोड उदाहरणों के साथ।
एजेंट एक लूप है: मॉडल बातचीत पढ़ता है, आपके एक या अधिक टूल कॉल करने का निर्णय लेता है, आप उन्हें चलाकर नतीजे वापस भेजते हैं, और मॉडल तब तक आगे बढ़ता है जब तक वह उत्तर न दे सके। api14 हर टूल-सक्षम मॉडल पर OpenAI tools फ़ॉर्मेट के साथ इसे सपोर्ट करता है, इसलिए केवल मॉडल id बदलकर वही कोड OpenAI, Anthropic, Google और अन्य प्रोवाइडर के साथ चलता है।
यह गाइड स्टेप लिमिट, समानांतर टूल निष्पादन, स्ट्रक्चर्ड अंतिम उत्तर और लागत नियंत्रण वाला एक छोटा एजेंट बनाती है। कोड आधिकारिक openai पैकेज और बेस URL https://api14.com/api/v1 का उपयोग करता है।
टूल परिभाषित करें
हर टूल में एक नाम, मॉडल के पढ़ने के लिए एक विवरण और उसके आर्गुमेंट के लिए एक JSON Schema होता है। विवरण स्पष्ट और विशिष्ट रखें; मॉडल के लिए यही एकमात्र दस्तावेज़ है।
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api14.com/api/v1", api_key=os.environ["API14_API_KEY"])
def search_orders(customer_email: str) -> list:
return [{"id": "A-1001", "status": "shipped"}] # आपकी डेटाबेस क्वेरी
def get_shipment(order_id: str) -> dict:
return {"order_id": order_id, "carrier": "UPS", "eta": "2026-10-09"} # आपकी API कॉल
TOOLS = {"search_orders": search_orders, "get_shipment": get_shipment}
tools = [
{"type": "function", "function": {
"name": "search_orders",
"description": "List a customer's orders with their status.",
"parameters": {"type": "object", "properties": {"customer_email": {"type": "string"}},
"required": ["customer_email"]},
}},
{"type": "function", "function": {
"name": "get_shipment",
"description": "Carrier and estimated delivery date for one order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}},
]
स्टेप लिमिट के साथ लूप
हर इटरेशन एक अलग बिल होने वाला अनुरोध है, इसलिए स्टेप की संख्या हमेशा सीमित रखें। टूल की त्रुटियाँ क्रैश करने के बजाय कंटेंट के रूप में मॉडल को लौटाएँ; मॉडल आमतौर पर आर्गुमेंट ठीक करके खुद संभल जाते हैं।
MAX_STEPS = 8
def run_tool(call):
try:
args = json.loads(call.function.arguments)
result = TOOLS[call.function.name](**args)
except Exception as e: # गलत JSON, अज्ञात टूल, या आपका फ़ंक्शन विफल हुआ
result = {"error": str(e)}
return {"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)}
def agent(task, model="openai/gpt-5-mini"):
messages = [
{"role": "system", "content": "You are a support agent. Use tools to look things up. Be brief."},
{"role": "user", "content": task},
]
spent = 0.0
for step in range(MAX_STEPS):
r = client.chat.completions.create(model=model, messages=messages, tools=tools, max_tokens=1000)
spent += r.usage.cost
msg = r.choices[0].message
if not msg.tool_calls:
return msg.content, spent
messages.append(msg)
messages.extend(run_tool(call) for call in msg.tool_calls)
raise RuntimeError(f"No answer after {MAX_STEPS} steps (spent ${spent:.4f})")
print(agent("Where is my order? My email is ada@example.com"))
लूप के हर अनुरोध में tools भेजें। कई प्रोवाइडर ऐसे अनुरोध में tool मैसेज अस्वीकार कर देते हैं जिसमें टूल परिभाषाएँ नहीं होतीं।
समानांतर टूल कॉल
parallel_tool_calls (जहाँ सपोर्ट है वहाँ डिफ़ॉल्ट रूप से चालू) के साथ मॉडल एक ही टर्न में कई कॉल माँग सकता है, उदाहरण के लिए तीन ऑर्डर के लिए get_shipment। उन्हें एक साथ चलाएँ और हर कॉल के लिए एक tool मैसेज जोड़ें, किसी भी क्रम में; tool_call_id हर नतीजे को उसकी कॉल से जोड़ता है। Node में:
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api14.com/api/v1", apiKey: process.env.API14_API_KEY });
const MAX_STEPS = 8;
async function agent(messages, tools, impl, model = "openai/gpt-5-mini") {
for (let step = 0; step < MAX_STEPS; step++) {
const res = await client.chat.completions.create({ model, messages, tools, max_tokens: 1000 });
const msg = res.choices[0].message;
if (!msg.tool_calls?.length) return msg.content;
messages.push(msg);
const results = await Promise.all(msg.tool_calls.map(async (call) => {
let content;
try {
content = JSON.stringify(await impl[call.function.name](JSON.parse(call.function.arguments)));
} catch (err) {
content = JSON.stringify({ error: String(err) });
}
return { role: "tool", tool_call_id: call.id, content };
}));
messages.push(...results);
}
throw new Error(`No answer after ${MAX_STEPS} steps`);
}
यदि आपके टूल के ऐसे साइड इफ़ेक्ट हैं जिन्हें क्रम से होना चाहिए (पहले बनाना, फिर अपडेट करना), तो parallel_tool_calls: false सेट करें ताकि मॉडल हर टर्न में केवल एक कॉल माँगे।
स्ट्रक्चर्ड अंतिम आउटपुट
जब एजेंट का उत्तर दूसरे कोड में जाता है, तो किसी schema से मेल खाता JSON माँगें। एक सरल और पोर्टेबल तरीका यह है कि लूप के तथ्य जुटा लेने के बाद एक अतिरिक्त कॉल की जाए (यहाँ messages लूप की बातचीत है; इसे agent() से उत्तर के साथ लौटाएँ):
schema = {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"status": {"type": "string", "enum": ["processing", "shipped", "delivered", "unknown"]},
"eta": {"type": ["string", "null"]},
"reply": {"type": "string"},
},
"required": ["order_id", "status", "eta", "reply"],
"additionalProperties": False,
}
final = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=messages + [{"role": "user", "content": "Summarize the result for our ticket system."}],
tools=tools,
tool_choice="none",
response_format={"type": "json_schema", "json_schema": {"name": "ticket", "strict": True, "schema": schema}},
)
ticket = json.loads(final.choices[0].message.content)
tool_choice: "none" अनुरोध में tools बनाए रखता है (इसकी ज़रूरत इसलिए है कि इतिहास में tool मैसेज हैं) और आगे की कॉल रोकता है। पार्स किए गए JSON को हमेशा validate करें। देखें स्ट्रक्चर्ड आउटपुट।
मॉडल चुनना
- क्षमता: मॉडल को
supported_parametersमेंtoolsसूचीबद्ध करना चाहिए।GET /modelsसे जाँचें, देखें मॉडल। अंतिम चरण के लिएstructured_outputsयाresponse_formatदेखें। - रूटिंग:
provider: { "require_parameters": true }जोड़ें (Python मेंextra_bodyके ज़रिए) ताकि अनुरोध केवल उन प्रोवाइडर तक जाएँ जो आपके भेजे हर पैरामीटर को सपोर्ट करते हैं। देखें प्रोवाइडर रूटिंग। - आकार:
openai/gpt-5-miniजैसे छोटे मॉडल कुछ अच्छी तरह वर्णित टूल को भरोसेमंद ढंग से और सस्ते में संभालते हैं। जब एजेंट के पास कई टूल हों, लंबी बहु-चरण योजनाएँ हों, या वह बार-बार गलत टूल चुने, तो बड़े मॉडल पर जाएँ। - अपने टूल के साथ परीक्षण करें: वही 20-50 वास्तविक कार्य दो या तीन उम्मीदवार मॉडल पर चलाएँ और सफलता दर, प्रति कार्य स्टेप और कुल
usage.costकी तुलना करें।
curl -s "https://api14.com/api/v1/models?category=text" \
| jq -r '.data[] | select(.supported_parameters | index("tools")) | "\(.id) \(.pricing.prompt)"'
लागत नियंत्रित करना
एक कार्य के लिए एजेंट कई अनुरोध कर सकता है, और हर स्टेप पर पूरी बातचीत फिर से भेजी जाती है। खर्च को कई स्तरों पर सीमित करें:
- स्टेप लिमिट (
MAX_STEPS) और हर अनुरोध परmax_tokens, जैसा ऊपर दिखाया गया है। - प्रति कार्य बजट: सभी स्टेप का
usage.costजोड़ें और सीमा पार होने पर रुक जाएँ। - छोटे टूल नतीजे: केवल वही फ़ील्ड लौटाएँ जो मॉडल को चाहिए। बड़े टूल आउटपुट का भुगतान बाद के हर स्टेप में इनपुट टोकन के रूप में होता है।
- प्रति-कुंजी दैनिक USD सीमा: API कुंजियाँ में एजेंट के लिए अलग कुंजी बनाएँ और दैनिक सीमा सेट करें। सीमा पूरी होने पर अनुरोध अगले UTC दिन तक
429 daily_limit_reachedलौटाते हैं; इस कोड पर एजेंट को रोकें, रीट्राई न करें। - मॉडल allowlist: कुंजी को केवल उन मॉडल तक सीमित करें जिन्हें आपने परखा है; बाकी सब
403 model_not_allowedलौटाते हैं। - प्रॉम्प्ट कैशिंग: सिस्टम प्रॉम्प्ट और टूल परिभाषाएँ हर अनुरोध में एक जैसी और सबसे पहले रखें ताकि कैश्ड प्रीफ़िक्स की छूट लागू हो। देखें प्रॉम्प्ट कैशिंग।
देखें टूल कॉलिंग, रेट लिमिट और त्रुटियाँ।