Průvodci
Úkoly
Úkol vytočí seznam příjemců jedním agentem podle pravidel, která nastavíš předem - rozpočet, volací okno, počet pokusů. Nic se nevytáčí, dokud úkol sám nespustíš.
Co je úkol
Úkol (task_...) je odchozí kampaň: jeden agent na motoru volai, seznam příjemců s telefonním číslem a volitelnými proměnnými pro systémový prompt, a pravidla (rozpočet, volací okno, maximální počet pokusů a délka hovoru). Tři typy podle účelu - invoice (upomínka platby), appointment (potvrzení termínu) a custom (cokoli jiného) - u prvních dvou navíc, když source je integration, každý příjemce nese referenci na doklad nebo událost (externalRefs), kterou agent v hovoru zmiňuje.
Agent musí být na vlastním motoru volai (useForOutboundTasks: true při založení, viz POST /v1/agents), ne na ElevenLabs - motor umí proměnné pro systémový prompt, stropy délky hovoru a ověření, že se za běhu kampaně nezměnila jeho konfigurace. Koncept agenta musí být PUBLIKOVANÝ (PATCH /v1/agents/{id} nebo POST /v1/agents/{id}/draft/publish) A publikovaná verze musí být OTESTOVANÁ (POST /v1/agents/{id}/simulate) - chybí-li kterýkoli krok, start vrátí agent_not_ready.
Stavy a přechody
V praxi jde úkol vždy ze `draft` rovnou do `running` (`start`); smazat (`DELETE`) jde jen v označených stavech.
draftstart. Editovatelný (PATCH), smazatelný.readydraft a running, který start jako výchozí bod akceptuje - žádný veřejný endpoint (REST ani MCP) do něj ale úkol dnes nepřevádí, takže ho v praxi nepotkáš. Kdyby nastal, je editovatelný a smazatelný stejně jako draft.runningPATCH vrátí task_not_editable bez výjimky. Kdo potřebuje změnit proměnné, musí úkol nejdřív zastavit (POST .../pause) a upravit až v paused - a jen dokud se ještě žádný příjemce nevytáčel; po prvním pokusu už recipients (a tím i proměnné) vyměnit nejde (items_immutable) a zbývá založit nový úkol. Smazat nejde. Když narazí na limit hovorů (rate_limited - limit odchozích minut vlastního motoru, strop jeho souběžných odchozích hovorů, výchozích 10 hovorů za minutu nebo 1000 za den), zůstává running: nastaví lastError: "rate_limited", pokus se nezapočítá a čekající kontakty dostanou items[].nextAttemptAt na konec limitu (podle Retry-After, jinak za 5 minut; u stropu souběžných hovorů motoru posílá motor Retry-After: 30). Po jeho uplynutí pokračuje sám. Stejně čeká při plné kvótě souběžných hovorů agenta na účet (relay_lease_limit, výchozí 2 běžící hovory): lastError: "relay_lease_limit", další pokus za minutu, pokus se nezapočítá. Obsazené číslo (destination_busy - na stejné číslo právě běží jiný hovor, třeba z jiného úkolu nebo ručního volání, nebo je po nejistém vytočení 15 minut zamčené) čeká jen dotčený kontakt, ne celý úkol: items[].lastError: "destination_busy", items[].nextAttemptAt podle zbývající doby zámku čísla (nejméně 30 s, nejvýš 16 min, bez zámku 90 s), pokus se nezapočítá (countsAsAttempt: false) a ostatní kontakty se volají dál. Po 6. obsazení za sebou (tedy po 5 čekáních) jde kontakt do review s reviewReason: "dial:destination_busy". Trvalá překážka v čísle (on_dnc, destination_auto_blocked, cannot_call_own_number, cannot_call_volai_number, invalid_number, unsupported_country, blocked_destination) úkol také nezastaví: kontakt jde do review s reviewReason: "dial:<kód>" (hovor nevznikl, takže pokus má countsAsAttempt: false a nečerpá maxAttempts), úkol zůstává running, volá ostatní kontakty a do needs_attention přejde, až nezbude jiná práce. Když provozovatel volai agenta úkolu ručně pozastaví, úkol zůstává running a nic nevytáčí; po obnovení pokračuje sám. Pozastaveného agenta poznáš podle suspended: true v GET /v1/agents/{id}.pausedPOST .../pause); rozvolaný hovor doběhne. Editovatelný, smazatelný, start ho obnoví. Pozastavení uprostřed hovoru nechá reviewReason: "dispatch_in_flight", dokud reconcile (plánovač ho spustí do pár minut) ten hovor nevyúčtuje, a do té doby start odmítne s task_needs_attention; potom úkol s prací zůstane paused, i když jiné kontakty čekají v review. Skončí-li rozvolaný hovor bez známé ceny, přejde úkol nejdřív do needs_attention s reviewReason: "billing_unknown" a do paused se vrátí, až cena dorazí (reconcile ji doplní). Snížíš-li mezitím maxAttempts tak, že žádný kontakt čekající na další pokus už nemá volný pokus, zůstane úkol paused (takový kontakt se počítá jako práce), ale start ho odmítne s task_not_startable, dokud maxAttempts nezvýšíš.completedneeds_attentionagent_version_changed), motor dočasně nešel (engine_contract_unavailable) nebo ještě není známá cena už proběhlého hovoru (billing_unknown). POST .../reconcile sladí stav; smazatelný, dokud žádná položka nezůstala in_progress. Kontakt ve stavu review vyřídíš přes POST .../items/{itemId}/resolve (retry/skip); kontakt s trvalou překážkou v čísle (dial:on_dnc, dial:destination_auto_blocked, dial:cannot_call_own_number, dial:cannot_call_volai_number, dial:invalid_number, dial:unsupported_country, dial:blocked_destination, nebo dial:destination_busy po 6. obsazení za sebou) tak úkol zastaví až ve chvíli, kdy ostatní kontakty doběhnou. Nejistý výsledek vytáčení (např. dial:engine_unavailable) pošle úkol do needs_attention hned a ostatní kontakty se nevytočí. Až se hovor za takovým přerušením (nebo neznámou cenou) vyúčtuje přes reconcile, úkol přejde do paused, dokud některý kontakt čeká na další pokus, i když jiné jsou v review; do needs_attention jen když nezbývá nic k vytočení kromě kontaktu v review, a do completed, když nezbývá nic. Vytočení, jehož výsledek zůstává nejistý (hovor se nedohledá), drží úkol v needs_attention, dokud o kontaktu nerozhodneš. U běžného důvodu po posledním rozhodnutí úkol přejde do paused, pokud zbývá práce, nebo do completed, pokud jsou všechny kontakty hotové či přeskočené. Důvod na úrovni celého úkolu zůstává v needs_attention do svého vyřešení; výjimkou je budget_exceeded, kdy přeskočení všech kontaktů čekajících na další pokus úkol dokončí, pokud už nečeká žádný stav poskytovatele. Zvláštní postup pro billing_unknown je níže.Přesná podmínka smazání: stav je jeden z výše označených A ŽÁDNÁ položka nemá status: "in_progress" (rozvolaný hovor, který ještě neskončil) - jinak task_not_deletable.
Import příjemců (CSV)
POST /v1/tasks/csv-preview naparsuje CSV a vrátí ho zpátky s chybami u jednotlivých řádků - NIC se neukládá, jde jen o náhled před založením nebo úpravou úkolu. Stejnou funkci volá i formulář nového úkolu v portálu.
- Oddělovač se pozná automaticky (čárka nebo středník) podle prvního řádku.
- Musí existovat sloupec
phone- velikost písmen, mezery kolem názvu ani dvojtečka za ním nerozhodují a projde itelefon,telnebomobil; v náhledu se sloupec vrací vždy jakophone. Samotný seznam čísel bez hlavičky (jedno na řádek, jediný sloupec) projde také. Jinak celé CSV padá na jedinou chybuphoneu hlavičky. - Každý další sloupec je proměnná pro systémový prompt agenta (
{{jméno_sloupce}}) - nejvýš 20 sloupců, název max 64 znaků, hodnota max 512 znaků. - Telefonní číslo se normalizuje stejně jako všude v API (
normalizePhone) - neplatné nebo prázdné číslo je chyba jen na TOM řádku, zbytek CSV se dál zpracuje. - Buňka, která vypadá jako vzorec tabulkového procesoru (začíná
=,+,-nebo@), se odmítne - ochrana proti CSV injection při otevření v Excelu. - Nejvýš 1000 řádků na jedno CSV (stejný strop jako počet příjemců úkolu) a 1 MB syrového textu; celý úkol i s podklady se musí vejít do 2 MB, jinak založení vrátí
validation.
Odpověď nese headers, delimiter, rows (každý řádek se svými chybami), validRows (jen bezvadné, přesně ve tvaru, který recipients v POST /v1/tasks očekává) a souhrnné errors. Pošli validRows rovnou jako recipients při založení nebo úpravě úkolu.
Rozpočet a volací okno
Rozpočet
budgetHal je STROP útraty v haléřích za celý úkol. Při založení musí pokrýt aspoň jeden pokus v maximální délce (budget_too_low, jinak); při startu se před KAŽDÝM vytočením rezervuje nejvyšší možná cena pokusu (reservedBudgetHal), teprve zvednutý hovor ji promítne do spentHal. Rezervace je cena hovoru přesně v délce maxDurationSecs (noha hovoru a noha agenta, každá zaokrouhlená nahoru na haléř stejně jako při účtování) a hovor ukončený stropem délky se účtuje nejvýš za maxDurationSecs, i když skončí o zlomek vteřiny později. Úkol nikdy neutratí víc, než kolik mu dáš do budgetHal.
Volací okno
callingWindow je {timezone: "Europe/Prague", start, end, days} - dnes jediné podporované pásmo je pražské, start/end ve tvaru HH:MM (konec včetně celé minuty: okno 09:00-18:00 pustí poslední hovor v 18:00:59, okno do 23:59 pokrývá celý den) a days čísla 0-6 (0 = neděle). Bez zadání platí pracovní dny 9:00-18:00. Mimo okno start vrátí window_closed - buď počkej na otevření, nebo oknem upravíš přes PATCH. Volitelné expiresAt je konec kampaně jako kladné bezpečné celé číslo v Unix milisekundách. Kontroluje se při startu a před každým vytočením včetně prvního. Od tohoto okamžiku nový hovor nezačne a pokus se nespotřebuje; probíhající hovor doběhne. Horizont opakování politiky lorela_enterprise (retryMaxAgeDays, výchozí 5) se naopak počítá jako N × 24 hodin od prvního započítaného pokusu, nikoli od založení úkolu.
Pokusy a délka hovoru
maxAttempts je bez politiky 1-3 (výchozí 1), s retryPolicy: "lorela_enterprise" 1-4 (při založení výchozí 4). Určuje nejvyšší počet automatických vytočení jednoho kontaktu včetně prvního (1 = bez opakování). Počítá se každý pokus, při kterém hovor mohl proběhnout, tedy i nezvednutý nebo odmítnutý volaným a pokus s nejistým výsledkem. Nepočítá se pokus, který volai odmítl ještě před vytočením (například blokované, vlastní nebo neplatné číslo, seznam nevolat, číslo, na které právě běží jiný hovor, limity hovorů); takový pokus má items[].attempts[].countsAsAttempt: false. Nepočítá se ani hovor, kterému operátor nedostal včas cíl, takže telefon volaného vůbec nezazvonil (pokus má errorCode: "relay_not_routed", hovor endReason: "rejected"): kontakt dostane nový pokus nejdřív za minutu (s politikou lorela_enterprise podle jejího rozvrhu) a po třetím takovém pokusu za sebou jde ke kontrole s reviewReason: "call:relay_not_routed". Bez politiky platí strop jen pro automatická vytočení: kontakt, kterému po vyčerpání pokusů dáš resolve s action: "retry", dostane ještě jedno vytočení navíc. maxDurationSecs (30-300) je strop délky JEDNOHO hovoru, po kterém se automaticky ukončí - výchozí délka je 120 sekund. Volitelná politika lorela_enterprise se zapíná přes API nebo MCP před prvním pokusem; stávající úkoly se samy nemění. Druhý pokus je nejdřív 8 minut od začátku prvního skutečného pokusu v době 08:00-22:00 Europe/Prague. Třetí jde do dalšího jiného okna 08:00-09:00 nebo 17:00-19:00, čtvrtý do opačného okna následující kalendářní den. Vždy platí také callingWindow a jeho dny; po horizontu opakování už politika znovu nevolá: volitelný retryMaxAgeDays je celé číslo dní 1-30 (bez zadání 5) a platí jen s politikou. Horizont končí N × 24 hodin od prvního započítaného pokusu kontaktu (pevné 24hodinové dny, takže přes změnu času se místní čas konce posune o hodinu). Jde změnit přes PATCH i po začátku pokusů (ne u úkolu running nebo completed, ten upravit nejde): zvýšení u pozastaveného úkolu vrátí kontakty, které propadly jen kvůli horizontu (reviewReason: "retry_age_expired"), zpět do stavu failed (čekají na další pokus) s novým nextAttemptAt, mají-li ještě volný pokus a nejbližší slot rozvrhu padne do nového horizontu a před expiresAt; snížení nic neotevře. Znovu otevírá jen PATCH, který horizont zvyšuje, proto retryMaxAgeDays a prodloužený expiresAt posílej v jednom požadavku. Opakuje jen no_answer, missed, busy, dokončenou hlasovou schránku a zvednutý hovor, ve kterém volaný nic neřekl (vše bez kontaktu s člověkem). Kontakt s člověkem, odmítnutí a chyba motoru automatické opakování zastaví; nejasný výsledek jde ke kontrole. Poslední dovolený pokus (maxAttempts), který skončí takovým opakovatelným výsledkem (nezvednuto, obsazeno, hlasová schránka nebo zvednutý hovor, ve kterém volaný nic neřekl), uzavře kontakt jako skipped s reviewReason: "retry_policy_exhausted" (jako retry_age_expired po vypršení horizontu): není co kontrolovat ani opakovat. Nejasný výsledek posledního pokusu zůstane v review se stejným důvodem. Bez politiky se nic nemění: poslední nezvednutý pokus je dál review. Ověřený lidský callback po vyčerpání pokusů kontakt přepne na completed. DNC, rozpočet a limity zůstávají v platnosti: automatická blokace po 3 neúspěších za 24 hodin může zastavit i čtvrtý pokus. Při PATCH bez maxAttempts zůstane dosavadní limit. S politikou vrací ruční resolve s action: "retry" chybu validation; povolené jsou jen její automaticky naplánované pokusy. Výjimkou je obnova prokazatelně nevytočeného zaniklého claimu před prvním skutečným pokusem: bez aktivního workeru, dispatch záměru, provider call ID, rezervace, ceny nebo callbacku a jen s prokázanými odmítnutími před vytočením v historii. Obnova zachová historii a stropy a vrátí kontakt mezi čekající v pozastavené úloze; sama nevolá. Připomínky takto znovu otevřít nelze. Ruční opakování tedy neobejde čtyři pokusy, horizont opakování ani ukončení po kontaktu s člověkem.
Globální propustnost
Vytáčení všech úkolů na CELÉ platformě (ne jen tvého účtu) prochází jedním cronem, který běží každé 2 minuty a zpracuje nejvýš 20 položek za běh - ALE tenhle strop se dělí mezi souběžně běžící úkoly, ne že by ho směl vyčerpat jeden úkol: z KAŽDÉHO aktivního úkolu se za jeden běh vytočí právě JEDEN příjemce. I na úplně prázdné platformě proto jeden úkol nikdy nevytočí víc než jednoho příjemce za 2 minuty - sto příjemců tak neproběhne za ~20 minut, ale za zhruba 200 minut (100 x 2 minuty). Naplánuj podle toho volací okno u časově citlivých kampaní (např. appointment den před termínem).
Postup pro agenta
Typický běh, v tomto pořadí:
- Agent úkolu musí být PUBLIKOVANÝ a publikovaná verze OTESTOVANÁ (
POST /v1/agents/{id}/draft/publish, pakPOST /v1/agents/{id}/simulate) - jinak pozdějšístartvrátíagent_not_ready. - Volitelně
POST /v1/tasks/csv-preview- zkontroluje CSV příjemců, než se založí úkol. POST /v1/tasks- založí úkol ve stavudraft. Nic se nevytáčí.GET /v1/tasks/{id}- přečtiissues(dry-run validace) a ověř, že úkol je připravený na start.- Podle potřeby
PATCH /v1/tasks/{id}- uprav pravidla, VŽDY serevisionz posledního čtení. POST /v1/tasks/{id}/start- spustí vytáčení. Každý zvednutý hovor se účtuje ihned.POST /v1/tasks/{id}/pausekdykoli za běhu,POST /v1/tasks/{id}/startznovu obnoví.- Po přerušení (pozastavení uprostřed hovoru, zaniklý claim, hovor s dosud neznámou cenou nebo nejisté vytočení, ke kterému se hovor dohledal)
POST /v1/tasks/{id}/reconcilesladí stav se skutečnými hovory; takový úkol s prací skončí vpaused, i když některé kontakty čekají vreview, a jde ho znovu spustit přesstart. Běžící úkol ani jiný důvod (variables_limit, selhání ověření faktury nebo kalendáře, nejisté vytočení, ke kterému se hovor nedohledal)reconcilenemění; kontakty ke kontrole vyřiď přesresolve. - Kontakt, který skončil ke kontrole (
items[].status: "review"), vyřiďPOST /v1/tasks/{id}/items/{itemId}/resolvesaction: "retry"nebo"skip". U běžného důvodu vrátíretrykontakt mezi čekající a úkol dopaused;skipho uzavře a úkol přejde dopaused, pokud zbývá práce, nebo docompleted, pokud jsou všechny kontakty hotové či přeskočené. Úkol vpausedpak obnovPOST /v1/tasks/{id}/start. - Když má kontakt
reviewReason: "dial:destination_auto_blocked", číslo je 30 dní automaticky blokované po opakovaně nezvednutých hovorech a samotnýretryho neodblokuje - kontakt by se hned vrátil doreview. Nejdřív zruš blokaci (POST /v1/dnc/{e164}/unblock, v MCPunblock_destination, číslo vezmi zitems[].phone), potomresolvesaction: "retry". Udial:on_dncnejdřív odeber číslo ze seznamu nevolat (DELETE /v1/dnc/{e164}), jinak kontakt přeskoč. U vlastního čísla účtu, čísla jiného účtu volai, neplatného čísla, čísla mimo Česko a Slovensko a prémiové linky (dial:cannot_call_own_number,dial:cannot_call_volai_number,dial:invalid_number,dial:unsupported_country,dial:blocked_destination) další pokus nepomůže: použij jenskip. - Když má kontakt
reviewReason: "billing_unknown", původní hovor už mohl proběhnout, jen ještě nemá známou cenu. Nejprve zavolejreconcilea zkontroluj navázaný hovor.retrysi zapamatuje, že se má kontakt zkusit znovu, ale nový hovor nepovolí, dokud se původní cena neusadí; potom úkol přejde dopauseda vyžaduje novýstart.skipzabrání dalšímu hovoru; původní hovor zůstává navázaný a jeho rezervace se dál počítá do rozpočtu, dokud se cena neusadí. Zbývá-li práce, úkol poskippřejde rovnou dopauseda jde spustit; bez další práce počká vneeds_attentiona po usazení ceny skončí vcompleted. Hovor, který se vůbec nevytočil (motor ho odmítl), se nikdy neúčtuje a usadí se hned na 0. DELETE /v1/tasks/{id}na konci, pokud úkol nikdy neproběhl nebo už doběhl a chceš záznam smazat.
Skoro každé zapisující volání (PATCH, start, pause, DELETE) bere revision z posledního přečtení úkolu - stejná optimistická souběžnost jako u konceptů agenta. Neshoda vrátí revision_conflict: načti úkol znovu (GET) a zopakuj s aktuální revision. reconcile je výjimka - revision je tam nepovinná.
MCP
Stejné nástroje jako REST (list_tasks, get_task, create_task, update_task, pause_task, resolve_task_item, reconcile_task, start_task) - kromě jednoho rozdílu u startu.
start_task potvrzuje čísla
MCP start_task bere navíc confirmedRecipients a confirmedBudgetHal - musí přesně sedět na skutečný počet příjemců a rozpočet úkolu, jinak vrátí validation s vypsanými skutečnými hodnotami a NIC nespustí. Cizí AI agent na jednom nejasně pochopeném pokynu tak nemůže omylem rozjet placenou kampaň na vymyšlených číslech - REST POST .../start tuhle mechaniku nemá, protože tam volá přímo vlastník účtu vlastním klíčem.
delete_task a náhled CSV v MCP nejsou - smazání zůstává v REST a portálu (nevratná akce s opsáním názvu), CSV náhled je jen krok formuláře.
Chyby
task_not_found- Žádný úkol s tímhleidna účtu není.task_not_editable- Úkol běží nebo je hotový (running/completed), nebo jeneeds_attentionbez možnosti obnovy - pravidla teď měnit nejdou. Stejný kód vrací iPOST .../items/{itemId}/resolveu běžícího úkolu: kontakt vreviewse objeví, už když úkol volá ostatní kontakty a je ještěrunning- počkej, až přejde doneeds_attention, nebo ho pozastav (POST .../pause).items_immutable- Seznam příjemců nejde nahradit poté, co se aspoň jeden pokus o vytočení odehrál.budget_too_low- Rozpočet nepokryje ani jeden pokus v maximální délce hovoru - zvyšbudgetHalnebo snižmaxDurationSecs.task_not_startable- Úkol není ve stavudraft/ready/paused, nebo nemá žádného čekajícího příjemce.task_needs_attention- Před dalším startem je potřebaPOST .../reconcile- něco (verze agenta, motor) se za běhu změnilo.agent_not_ready- Koncept agenta buď není publikovaný, nebo publikovaná verze není otestovaná - publikuj ho (POST /v1/agents/{id}/draft/publish) a pak otestuj publikovanou verzi (POST /v1/agents/{id}/simulate) před startem.agent_version_changed- Konfigurace agenta se změnila BĚHEM běžícího úkolu - otestuj a restartuj přesreconcile.engine_required- Agent úkolu není na motoru volai (useForOutboundTasks: true) - odchozí kampaně dnes vyžadují motor, ne ElevenLabs.engine_contract_unavailable- Motor momentálně neinzeruje podporu pro proměnné a stropy odchozích úkolů - zkus start znovu později.window_closed- Mimo nastavené volací okno - počkej na otevření, nebo upravcallingWindow.task_not_running- Pauza jde jen u běžícího úkolu.item_not_resolvable- Kontakt není ve stavureview- rozhodnout (retry/skip) jde jen o kontaktu čekajícím na kontrolu, a jen u úkolu, který neběží.task_not_deletable- Smazat jde jen úkol bez položkyin_progressve stavudraft/ready/paused/completed/needs_attention.revision_conflict- Úkol se mezitím změnil - načti ho znovu (GET) a zopakuj s aktuálnírevision.
Úplnou tabulku chyb pro každý endpoint najdeš v sekci Úkoly v REST API referenci.
Související
MCP server
Připojení Claude Code, Codex CLI, Codex desktopu, Cursoru a dalších AI editorů.
REST API
Kompletní reference všech endpointů: čísla, hovory, SMS, SMS čísla pro příjem, agenti a jejich koncepty, nástroje, nahrávky, webhooky, seznam nevolat, relay, účet, úkoly, kredit, doklady, kalendáře a integrace.
Hlasový agent
Systémový prompt, nástroje, přepojení na člověka, nahrávky a zapsané údaje z hovoru.