नेविगेशन पर जाएँ

कोड के रूप में वर्कफ़्लो

Python और JavaScript SDK के साथ एजेंट वर्कफ़्लो बनाएं, संपादित करें और वर्ज़न करें

ओवरव्यू

एक वर्कफ़्लो नोड और एज के ग्राफ़ के रूप में स्टोर होता है। उस ग्राफ़ को हाथ से लिखने का मतलब है कि आपको एज ID, edge_order लिस्ट और कंडीशन ऑब्जेक्ट को खुद एक-जैसा रखना होगा। Python और JavaScript SDK में Workflow बिल्डर आपको चेन किए गए मेथड कॉल के साथ वही ग्राफ़ बताने देता है। फिर यह वह workflow वैल्यू बनाता है जिसे agents.create() और agents.update() पहले से स्वीकार करते हैं।

इसका इस्तेमाल इन कामों के लिए करें:

  • कोड में वर्कफ़्लो बनाएं और किसी भी दूसरे कोड बदलाव की तरह उसका रिव्यू करें।
  • किसी एजेंट का वर्कफ़्लो लोड करें, एक नोड बदलें और बाकी ग्राफ़ को बिना छेड़े वापस पुश करें।
  • वर्कफ़्लो को वर्ज़न कंट्रोल में JSON के रूप में स्टोर करें और CI में उन्हें वैलिडेट करें।

बिल्डर पूरी तरह SDK में चलता है। यह कोई नया API एंडपॉइंट कॉल नहीं करता, और इससे बनाया गया कुछ भी डैशबोर्ड के विज़ुअल एडिटर में खोला और संपादित किया जा सकता है।

ज़रूरी शर्तें

  • Python: elevenlabs पैकेज। बिल्डर को elevenlabs.agent_workflows से इंपोर्ट किया जाता है।
  • JavaScript: @elevenlabs/elevenlabs-js पैकेज। बिल्डर को पैकेज रूट से एक्सपोर्ट किया जाता है।

वर्कफ़्लो बनाएं

Workflow ऑब्जेक्ट स्टार्ट नोड को दर्शाता है। हर वर्ब एक नोड जोड़ता है और उसे लौटाता है, इसलिए आप उससे अगला स्टेप चेन कर सकते हैं:

PythonJavaScriptजोड़ता है
converse(id, prompt, **options)converse(id, prompt, options?)एक सबएजेंट नोड। एजेंट अपने निर्देशों में prompt जोड़कर बातचीत करता है।
tool(id, tool_ids, **options)tool(id, toolIds, options?)एक डिस्पैच टूल नोड, जो दिए गए टूल चलाता है।
transfer(id, destination, **options)transfer(id, destination, options?)किसी फ़ोन नंबर, SIP URI या दूसरे एजेंट को ट्रांसफ़र।
end(id="end")end(options?)एक एंड नोड। ID के बिना हर end() एक ही "end" नोड शेयर करता है।

रूटिंग मेथड तय करते हैं कि कौन-सा एज अगले नोड तक जाता है:

PythonJavaScriptबनाता है
when(condition)when(condition)एक कंडीशनल एज। स्ट्रिंग एक LLM कंडीशन है; Expr एक एक्सप्रेशन है।
on_success() / on_failure()onSuccess() / onFailure()टूल नोड से एक एज, जो टूल कॉल के सफल या विफल होने पर लिया जाता है।
on_result(success=..., failure=...)onResult({ success, failure })दोनों टूल रिज़ल्ट एज एक साथ।
go_to(node)goTo(node)पहले से मौजूद नोड का एक एज, मर्ज और लूप के लिए।
up()up()कोई एज नहीं। उस नोड को लौटाता है जिससे मौजूदा नोड चेन किया गया था, ताकि वहीं से चेनिंग जारी रखी जा सके। एक चेन में वर्कफ़्लो लिखें देखें।

वर्कफ़्लो पर सीधे कॉल किए गए वर्ब बिना शर्त वाले एज के साथ स्टार्ट नोड से ब्रांच करते हैं। यह उदाहरण कॉलर को ऑर्डर लुकअप पर भेजता है, लुकअप विफल होने पर पहचान की फिर से कोशिश करता है और VIP या निराश कॉलर को ट्रांसफ़र करता है:

from elevenlabs import ElevenLabs
from elevenlabs.agent_workflows import Destination, Expr, Workflow
elevenlabs = ElevenLabs()
wf = Workflow()
triage = wf.converse("triage", "Greet the caller and find out why they're calling")
identify = triage.when("Caller wants to check an order").converse(
"identify", "Ask for the order number and the email on the account"
)
lookup = identify.when("Caller gave an order number").tool("lookup_order", ["tool_get_order"])
lookup.on_result(
success=lambda ok: ok.converse("resolve", "Explain the order status")
.when("Caller is satisfied")
.end(),
failure=lambda failed: failed.go_to(identify),
)
triage.when(Expr.variable("tier").eq("gold")).transfer("vip", Destination.agent("agent_vip"))
triage.when("Caller wants a human").transfer("human", Destination.phone("+15551234567"))
elevenlabs.conversational_ai.agents.update("agent_id", workflow=wf.build())

build() पूरे ग्राफ़ को वैलिडेट करता है और रिक्वेस्ट मॉडल लौटाता है। यह ये काम भी करता है:

  • स्टार्ट नोड को API के लिए ज़रूरी ID start_node देता है।
  • source__target फ़ॉर्म में एज ID जनरेट करता है।
  • आपके एज जोड़ने के क्रम में हर नोड का edge_order भरता है।
  • जिस नोड की कोई पोज़िशन नहीं है, उसे पोज़िशन देता है, ताकि विज़ुअल एडिटर में ग्राफ़ बाएं से दाएं लेआउट हो।

एक चेन में वर्कफ़्लो लिखें

up() उस नोड को लौटाता है जिससे मौजूदा नोड चेन किया गया था, इसलिए हर नोड को वैरिएबल में रखने के बजाय आप पूरे वर्कफ़्लो को एक एक्सप्रेशन में बता सकते हैं। एक ही चेन में नोड ID के साथ go_to() / goTo() का इस्तेमाल करें, क्योंकि पास करने के लिए कोई वैरिएबल नहीं होता:

wf = Workflow()
(
wf.converse("triage", "Find out why the customer is calling")
.when("Caller gave an order number")
.tool("lookup_order", ["tool_get_order"])
.on_result(
success=lambda ok: ok.converse("resolve", "Explain the order status").when("Customer is satisfied").end(),
failure=lambda failed: failed.go_to("triage"),
)
.up()
.when(Expr.variable("tier").eq("gold"))
.transfer("vip", Destination.agent("agent_vip_desk"))
)
elevenlabs.conversational_ai.agents.update("agent_id", workflow=wf.build())

wf.node(id) से मिले नोड हैंडल के लिए, up() उस नोड को लौटाता है जिससे उसमें आने वाला पहला एज आता है। स्टार्ट नोड के लिए, यह स्टार्ट नोड लौटाता है।

नोड विकल्प

वैकल्पिक सेटिंग Python में कीवर्ड आर्ग्युमेंट और JavaScript में आखिर के ऑप्शन ऑब्जेक्ट में दी जाती हैं। उनके नाम API में नोड के फ़ील्ड से मेल खाते हैं:

नोडPythonJavaScript
converselabel, tool_ids, knowledge_base, conversation_config, entry_behaviorlabel, toolIds, knowledgeBase, conversationConfig, entryBehavior
toolschema_overridesschemaOverrides
transfertransfer_type, custom_sip_headers, post_dial_digits, delay_ms, transfer_message, …transferType, customSipHeaders, postDialDigits, delayMs, transferMessage, …
endidid

अगर आप नोड को खुद रखना चाहते हैं, तो हर वर्ब position भी स्वीकार करता है। Python में Workflow(prevent_subagent_loops=True) या JavaScript में new Workflow({ preventSubagentLoops: true }) बातचीत को पहले देखे जा चुके सबएजेंट में दोबारा प्रवेश करने से रोकता है।

triage = wf.converse(
"triage",
"Greet the caller and find out why they're calling",
label="Triage",
tool_ids=["tool_crm_search"],
entry_behavior="generate_immediately",
)
triage.when("Caller is a VIP").transfer(
"vip_desk",
Destination.agent("agent_vip_concierge"),
transfer_message="Connecting you to our VIP team",
delay_ms=500,
)
identify.when("Caller refuses to share details").end(id="abandoned")

ट्रांसफ़र डेस्टिनेशन

PythonJavaScriptट्रांसफ़र करता है
Destination.phone(number)Destination.phone(number)एक फ़ोन नंबर पर
Destination.phone_variable(name)Destination.phoneVariable(name)डायनामिक वैरिएबल में मौजूद फ़ोन नंबर पर
Destination.sip(uri)Destination.sip(uri)एक SIP URI पर
Destination.sip_variable(name)Destination.sipVariable(name)डायनामिक वैरिएबल में मौजूद SIP URI पर
Destination.agent(agent_id)Destination.agent(agentId)दूसरे एजेंट को

कंडीशन

when() एक साधारण स्ट्रिंग, Condition या Expr लेता है:

  • स्ट्रिंग एक LLM कंडीशन है: LLM तय करता है कि वह पूरी होती है या नहीं।
  • Condition.llm(text, label=...) भी यही है, जिसमें विज़ुअल एडिटर में एज पर दिखने वाला लेबल होता है। एक्सप्रेशन को लेबल करने के लिए Condition.expr(expr, label=...) इस्तेमाल करें।
  • Expr को LLM कॉल किए बिना डायनामिक वैरिएबल के आधार पर मूल्यांकित किया जाता है।

Expr.variable(name) और Expr.literal(value) से एक्सप्रेशन बनाएं। उनकी तुलना eq, neq, gt, gte, lt और lte से करें, और add, sub, mul और div से गणितीय ऑपरेशन करें। उन्हें all_of / allOf, any_of / anyOf और if_else / ifElse से जोड़ें। साधारण वैल्यू आपके लिए Expr.literal() में रैप हो जाती हैं। Expr.llm(description) बातचीत से वैल्यू निकालने के लिए LLM से कहता है; बूलियन के बजाय स्ट्रिंग, नंबर या तय सेट में से एक वैल्यू पाने के लिए type और enum पास करें।

from elevenlabs.agent_workflows import Condition, Expr
is_vip = Expr.any_of(
Expr.variable("tier").eq("gold"),
Expr.all_of(Expr.variable("orders").gte(10), Expr.variable("churn_risk").eq(True)),
)
triage.when(Condition.expr(is_vip, label="VIP")).transfer("vip_desk", Destination.agent("agent_vip"))
big_refund = Expr.variable("unit_price").mul(Expr.variable("quantity")).gt(500)
resolve.when(big_refund).transfer("finance", Destination.phone("+15551234567"))
score = Expr.llm("How satisfied the caller sounds, from 1 to 5", type="integer")
resolve.when(score.lte(2)).converse("recovery", "Apologize and offer a discount code")

लूप और बैकवर्ड एज

API किसी भी दो नोड के बीच, किसी भी दिशा में, एक एज की अनुमति देता है। बातचीत को वापस उसी रास्ते से लौटने देने के लिए, back के साथ एज को एक बैकवर्ड कंडीशन दें:

faq = triage.when("Caller has a general question", back="Question answered").converse(
"faq", "Answer using the FAQ knowledge base"
)

go_to() / goTo() आम स्थिति को आपके लिए संभालता है। जब टारगेट नोड में पहले से यहां आने वाला एज होता है, तो नया एज उस एज की बैकवर्ड कंडीशन बन जाता है। पहले उदाहरण में, failed.go_to(identify) को identify → lookup_order एज की बैकवर्ड कंडीशन के रूप में भेजा जाता है। उन्हीं दो नोड के बीच कोई भी दूसरा एज और किसी नोड से उसी नोड तक का कोई भी एज वैलिडेशन में विफल होता है।

मौजूदा एजेंट को संपादित करें

Workflow.from_agent() / Workflow.fromAgent() agents.get() से लौटे एजेंट का वर्कफ़्लो लोड करता है। नोड ID, एज ID, एडिटर पोज़िशन और एज ऑर्डर बनाए रखे जाते हैं, इसलिए इसे वापस पुश करने पर सिर्फ़ आपके किए बदलाव बदलते हैं।

PythonJavaScriptकाम
wf.node(id)wf.node(id)मौजूदा नोड को संपादित करने या उससे चेन करने के लिए उसका हैंडल लौटाता है।
node.update(**fields)node.update(fields)नोड का प्रॉम्प्ट, टूल, डेस्टिनेशन या विकल्प बदलता है।
wf.insert_between(source, target, fn)wf.insertBetween(source, target, fn)मौजूदा एज की कंडीशन बनाए रखते हुए उसमें नए नोड जोड़ता है।
wf.remove(id)wf.remove(id)एक नोड और उससे आने या जाने वाले हर एज को हटाता है।

insert_between() / insertBetween() आपके फ़ंक्शन को एक ब्रांच देता है जिसमें बदले गए एज की कंडीशन होती है। फ़ंक्शन अपने जोड़े गए आखिरी नोड को लौटाता है, जिसे फिर मूल टारगेट से जोड़ा जाता है। यह मेथड वह नोड लौटाता है, या अगर दोनों नोड के बीच कोई एज नहीं है तो None / undefined लौटाता है।

agent = elevenlabs.conversational_ai.agents.get("agent_id")
wf = Workflow.from_agent(agent)
wf.node("resolve").update(prompt="Explain the status, then offer a discount code")
verify = wf.insert_between(
"identify",
"lookup_order",
lambda start: start.converse("verify", "Verify the caller's identity with a one-time code"),
)
if verify is not None:
verify.when("Caller can't verify").end(id="unverified")
wf.remove("vip")
elevenlabs.conversational_ai.agents.update("agent_id", workflow=wf.build())

वर्कफ़्लो को वर्ज़न कंट्रोल में स्टोर करें

to_json_string() / toJSONString() API के वायर फ़ॉर्मैट में वर्कफ़्लो लिखता है: snake_case की, हर लेवल पर सॉर्ट की गईं, 2-स्पेस इंडेंटेशन के साथ। यह वही संरचना है जिसे REST API और CLI इस्तेमाल करते हैं, और दोनों SDK एक ही वर्कफ़्लो के लिए बाइट-फॉर-बाइट एक जैसी फ़ाइलें लिखते हैं, इसलिए डिफ़ छोटे रहते हैं। Workflow.from_json() / Workflow.fromJSON() इसे वापस पढ़ता है और workflow की वाली पूरी एजेंट कॉन्फ़िग भी स्वीकार करता है, जैसे CLI की agent_configs/ डायरेक्टरी में मौजूद फ़ाइल।

from pathlib import Path
from elevenlabs.agent_workflows import Workflow
Path("workflows/support.json").write_text(wf.to_json_string())
stored = Workflow.from_json(Path("workflows/support.json").read_text())
from_cli = Workflow.from_json(Path("agent_configs/support.json").read_text())

एक सामान्य सेटअप:

1

फ़ाइल तैयार करें

एजेंट को from_agent() / fromAgent() से लोड करके लिखें, या elevenlabs agents pull से पुल करें।

2

संपादित करें

JSON को सीधे बदलें, या from_json() / fromJSON() से लोड करें और स्क्रिप्ट में बिल्डर से संपादित करें।

3

CI में वैलिडेट करें

हर पुल रिक्वेस्ट पर Workflow.from_json(file).build() / Workflow.fromJSON(file).build() चलाएं, और elevenlabs agents workflow diagram <file> --format mermaid-md को कमेंट के रूप में पोस्ट करें, ताकि रिव्यूअर ग्राफ़ देख सकें।

4

मर्ज पर डिप्लॉय करें

बना हुआ वर्कफ़्लो agents.update() से पुश करें।

वर्कफ़्लो विज़ुअलाइज़ करें

CLI वर्कफ़्लो फ़ाइल को फ़्लोचार्ट के रूप में बनाता है, ताकि डैशबोर्ड खोले बिना आप देख सकें कि आपके कोड ने क्या बनाया। यह to_json_string() / toJSONString() से लिखी साधारण वर्कफ़्लो फ़ाइल या workflow की वाली एजेंट कॉन्फ़िग स्वीकार करता है:

elevenlabs agents workflow diagram workflows/support.json

डिफ़ॉल्ट रूप से यह टर्मिनल में बॉक्स और ऐरो बनाता है, जिसमें हर एज कंडीशन को उसके एज पर नंबर दिया जाता है और नीचे एक लीजेंड में लिखा जाता है। इसकी जगह Mermaid सोर्स प्रिंट करने के लिए --format mermaid इस्तेमाल करें, या इसे GitHub द्वारा रेंडर किए जाने वाले फेंस्ड कोड ब्लॉक में रैप करने के लिए --format mermaid-md इस्तेमाल करें, जैसे पुल रिक्वेस्ट कमेंट में:

elevenlabs agents workflow diagram workflows/support.json --format mermaid-md

कमांड सिर्फ़ लोकल फ़ाइलें पढ़ती है, इसलिए इसे API की की ज़रूरत नहीं होती और यह CI में चल सकती है।

वैलिडेशन

चेन किए गए कॉल अपने आप कभी विफल नहीं होते। build(), to_json() / toJSON() और to_json_string() / toJSONString() पूरे ग्राफ़ की जांच करते हैं और एक ही WorkflowValidationError को raise या throw करते हैं, जिसकी issues लिस्ट में हर समस्या होती है और हर समस्या के साथ उसका code, message और संबंधित node_id / nodeId होता है।

from elevenlabs.agent_workflows import WorkflowValidationError
try:
workflow = wf.build(on_warning=lambda issue: print("warning:", issue.message))
except WorkflowValidationError as err:
for issue in err.issues:
print(issue.code, issue.message)

एरर में ये शामिल हैं:

  • एक ही जोड़ी के नोड के बीच दो एज या किसी नोड से उसी नोड तक एक एज।
  • स्टार्ट नोड में आने वाला या एंड नोड से बाहर जाने वाला एज।
  • टूल नोड से ऐसा एज जो सफलता या विफलता एज नहीं है, या किसी और तरह के नोड से सफलता या विफलता एज।
  • एक ही ID वाले दो नोड या ऐसे नोड का एज जो मौजूद नहीं है।

स्टार्ट नोड से न पहुंच सकने वाले नोड on_warning / onWarning के ज़रिए चेतावनी के रूप में रिपोर्ट होते हैं और बिल्ड को नहीं रोकते।

आपके SDK से नए नोड टाइप

API या फ़ाइल से लोड किए गए वर्कफ़्लो में ऐसे नोड टाइप हो सकते हैं जिन्हें आपका SDK वर्ज़न अभी नहीं जानता। वे from_json() / fromJSON() और to_json_string() / toJSONString() के ज़रिए बिना बदलाव के राउंड-ट्रिप होते हैं, और build() हर एक को चेतावनी के रूप में रिपोर्ट करता है। टाइप किया हुआ रिक्वेस्ट मॉडल उन्हें नहीं ले जा सकता, इसलिए SDK अपग्रेड करें या वायर फ़ॉर्मैट सीधे भेजें:

elevenlabs.conversational_ai.agents.update(
"agent_id",
request_options={"additional_body_parameters": {"workflow": wf.to_json()}},
)