Ръководства
Задачи
Задачата набира списък от получатели с един агент по правила, които задавате предварително - бюджет, времеви прозорец за обаждания, брой опити. Нищо не се набира, докато сами не пуснете задачата.
Какво е задача
Задачата (task_...) е изходяща кампания: един агент на двигателя на volai, списък от получатели с телефонен номер и по избор променливи за системния промпт, и правила (бюджет, времеви прозорец за обаждания, максимален брой опити и продължителност на обаждането). Три типа според целта - invoice (напомняне за плащане), appointment (потвърждение на час) и custom (всичко останало) - при първите два, когато source е integration, всеки получател допълнително носи препратка към документа или събитието (externalRefs), които агентът споменава по време на обаждането.
Агентът трябва да е на собствения двигател на volai (useForOutboundTasks: true при създаването, вижте POST /v1/agents), а не на ElevenLabs - двигателят поддържа променливи за системния промпт, ограничения на продължителността на обаждането и проверка, че конфигурацията му не се е променила, докато кампанията е вървяла. Черновата на агента трябва да е ПУБЛИКУВАНА (PATCH /v1/agents/{id} или POST /v1/agents/{id}/draft/publish) И публикуваната версия трябва да е ТЕСТВАНА (POST /v1/agents/{id}/simulate) - ако липсва някоя от стъпките, start връща agent_not_ready.
Състояния и преходи
На практика задачата винаги минава от `draft` направо в `running` (`start`); изтриване (`DELETE`) е възможно само в отбелязаните състояния.
draftstart още не е минавал. Може да се редактира (PATCH) и да се изтрие.readydraft и running, което start приема като начална точка - но никоя публична крайна точка (нито REST, нито MCP) днес не прехвърля задача в него, така че на практика няма да го срещнете. Ако все пак настъпи, може да се редактира и изтрива като draft.runningPATCH връща task_not_editable без изключение. Който трябва да промени променливи, първо трябва да спре задачата (POST .../pause) и да я редактира в paused - и то само докато още не е набиран никой получател; след първия опит recipients (а с тях и променливите) вече не могат да се сменят (items_immutable) и остава да създадете нова задача. Не може да се изтрие. Когато достигне лимит на обажданията (rate_limited - лимит на изходящите минути на собствения двигател, таван на едновременните му изходящи обаждания, по подразбиране 10 обаждания в минута или 1000 на ден), остава running: задава lastError: "rate_limited", опитът не се брои, а чакащите контакти получават items[].nextAttemptAt в края на лимита (според Retry-After, иначе след 5 минути; при тавана на едновременните обаждания на двигателя той изпраща Retry-After: 30). След изтичането му продължава сама. По същия начин изчаква, когато е запълнена квотата на акаунта за едновременни обаждания на агента (relay_lease_limit, по подразбиране 2 текущи обаждания): lastError: "relay_lease_limit", следващ опит след минута, опитът не се брои. Зает номер (destination_busy - към същия номер в момента тече друго обаждане, например от друга задача или от ръчно обаждане, или номерът е заключен 15 минути след несигурно набиране) кара да чака само засегнатия контакт, а не цялата задача: items[].lastError: "destination_busy", items[].nextAttemptAt според оставащото време на заключването на номера (най-малко 30 с, най-много 16 мин, без заключване 90 с), опитът не се брои (countsAsAttempt: false), а останалите контакти продължават да се набират. След 6-ото заето подред (т.е. след 5 изчаквания) контактът отива в review с reviewReason: "dial:destination_busy". Траен проблем с номера (on_dnc, destination_auto_blocked, cannot_call_own_number, cannot_call_volai_number, invalid_number, unsupported_country, blocked_destination) също не спира задачата: контактът отива в review с reviewReason: "dial:<code>" (обаждане не е възникнало, затова опитът има countsAsAttempt: false и не изразходва maxAttempts), задачата остава running, набира останалите контакти и преминава в needs_attention едва когато не остане друга работа. Ако операторът на volai ръчно спре агента на задачата, задачата остава running и нищо не набира; след възстановяването продължава сама. Спрения агент ще познаете по suspended: true в GET /v1/agents/{id}.pausedPOST .../pause); започнатото обаждане приключва. Може да се редактира, изтрива, а start я възобновява. Пауза по средата на обаждане оставя reviewReason: "dispatch_in_flight", докато reconcile (планировчикът го пуска до няколко минути) не уреди това обаждане, а дотогава start се отхвърля с task_needs_attention; след това задача с останала работа остава paused, дори други контакти да чакат в review. Пауза, която попадне точно преди самото обаждане (обаждане още не е възникнало), не оставя dispatch_in_flight: планировчикът връща контакта сред чакащите, а задачата веднага е paused без причина. Контакт, чиято обработка е прекъсната от срив, преди да възникне обаждане, се освобождава от reconcile най-рано 15 минути след началото на набирането (claim от 10 минути плюс резерв от 5 минути) и се връща сред чакащите; задача, спряна междувременно от изтекъл claim (dispatch_claim_expired), след това преминава в paused. Ако започнатото обаждане приключи без позната цена, задачата първо преминава в needs_attention с reviewReason: "billing_unknown" и се връща в paused, щом цената пристигне (reconcile я допълва). Ако междувременно намалите maxAttempts така, че нито един контакт, чакащ следващ опит, да няма свободен опит, задачата остава paused (такъв контакт се брои за работа), но start я отхвърля с task_not_startable, докато не увеличите maxAttempts.completedneeds_attentionagent_version_changed), двигателят временно е бил недостъпен (engine_contract_unavailable) или още не е позната цената на вече проведено обаждане (billing_unknown). POST .../reconcile сверява състоянието; може да се изтрие, докато никоя позиция не е останала in_progress. Контакт в състояние review уреждате чрез POST .../items/{itemId}/resolve (retry/skip); контакт с траен проблем с номера (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 или dial:destination_busy след 6-ото заето подред) спира задачата едва когато останалите контакти приключат. Несигурен резултат от набирането (напр. dial:engine_unavailable) праща задачата в needs_attention веднага и останалите контакти не се набират. Когато обаждането зад такова прекъсване (или неизвестна цена) бъде уредено чрез reconcile, задачата преминава в paused, докато някой контакт чака следващ опит, дори други да са в review; в needs_attention само когато не остава нищо за набиране освен контакт в review, и в completed, когато не остава нищо. Набиране, чийто резултат остава несигурен (обаждането не се намира), държи задачата в needs_attention, докато не вземете решение за контакта. При обичайна причина след последното решение задачата преминава в paused, ако остава работа, или в completed, ако всички контакти са приключени или пропуснати. Причина на ниво цяла задача остава в needs_attention до разрешаването си; изключение е budget_exceeded, при което пропускането на всички контакти, чакащи следващ опит, завършва задачата, ако не чака никакво състояние при доставчика. Специалният ред за billing_unknown е описан по-долу.Точното условие за изтриване: състоянието е едно от отбелязаните по-горе И НИКОЯ позиция няма status: "in_progress" (започнато обаждане, което още не е приключило) - иначе task_not_deletable.
Импорт на получатели (CSV)
POST /v1/tasks/csv-preview разчита CSV и го връща обратно с грешките по отделните редове - НИЩО не се запазва, това е само преглед преди създаване или редакция на задача. Същата функция извиква и формулярът за нова задача в портала.
- Разделителят се разпознава автоматично (запетая или точка и запетая) по първия ред.
- Трябва да съществува колона
phone- малките и главните букви, интервалите около името и двоеточието след него нямат значение, приемат се иtelefon,telилиmobil; прегледът винаги връща колоната катоphone. Минава и просто списък с номера без заглавен ред (по един на ред, една колона). Иначе целият CSV пада с единствената грешкаphoneпри заглавния ред. - Всяка следваща колона е променлива за системния промпт на агента (
{{column_name}}) - най-много 20 колони, име до 64 знака, стойност до 512 знака. - Телефонният номер се нормализира както навсякъде в API (
normalizePhone) - невалиден или празен номер е грешка само на ТОЗИ ред, останалата част от CSV се обработва нататък. - Клетка, която прилича на формула от електронна таблица (започва с
=,+,-или@), се отхвърля - защита срещу CSV инжекция при отваряне в Excel. - Най-много 1000 реда в един CSV (същият таван като броя получатели на задача) и 1 MB суров текст; цялата задача заедно с материалите трябва да се събере в 2 MB, иначе създаването връща
validation.
Отговорът съдържа headers, delimiter, rows (всеки ред със своите грешки), validRows (само безупречните, точно във вида, който очаква recipients в POST /v1/tasks) и обобщено errors. Изпратете validRows направо като recipients при създаване или редакция на задачата.
Бюджет и времеви прозорец за обаждания
Бюджет
budgetHal е ТАВАНЪТ на разходите за цялата задача в хелери. При създаване трябва да покрива поне един опит с максимална продължителност (иначе budget_too_low); при пускане преди ВСЯКО набиране се резервира най-високата възможна цена на опита (reservedBudgetHal) и едва вдигнатото обаждане я прехвърля в spentHal. Резервацията е цената на обаждане с продължителност точно maxDurationSecs (участъкът на обаждането и участъкът на агента, всеки закръглен нагоре до хелер, както при таксуването), а обаждане, прекратено от тавана на продължителността, се таксува най-много за maxDurationSecs, дори да приключи с част от секундата по-късно. Задачата никога не изразходва повече от budgetHal, който сте ѝ задали.
Времеви прозорец за обаждания
callingWindow е {timezone: "Europe/Prague", start, end, days} - днес единствената поддържана часова зона е пражката, start/end във вида HH:MM (краят включва цялата минута: прозорец 09:00-18:00 пуска последно обаждане в 18:00:59, прозорец до 23:59 покрива целия ден), а days са числа 0-6 (0 = неделя). Без задаване важат работните дни 9:00-18:00. Извън прозореца start връща window_closed - или изчакайте отварянето, или променете прозореца с PATCH. Незадължителното expiresAt е краят на кампанията като положително безопасно цяло число в Unix милисекунди. Проверява се при пускане и преди всяко набиране, включително първото. От този момент ново обаждане не започва и опит не се изразходва; текущо обаждане приключва. Хоризонтът за повторения на политиката lorela_enterprise (retryMaxAgeDays, по подразбиране 5), напротив, се брои като N × 24 часа от първия отчетен опит, а не от създаването на задачата.
Опити и продължителност на обаждането
maxAttempts е 1-3 без политика (по подразбиране 1), с retryPolicy: "lorela_enterprise" 1-4 (при създаване по подразбиране 4). Определя най-големия брой автоматични набирания на един контакт, включително първото (1 = без повторения). Брои се всеки опит, при който обаждането е могло да се състои, т.е. и невдигнато, и отказано от набирания, и опит с несигурен резултат. Не се брои опит, който volai е отхвърлил още преди набирането (например блокиран, собствен или невалиден номер, списък за недопускане на обаждания, номер, към който в момента тече друго обаждане, лимити на обажданията); такъв опит има items[].attempts[].countsAsAttempt: false. Не се брои и обаждане, на което операторът не е получил навреме дестинацията, така че телефонът на набирания изобщо не е звънял (опитът има errorCode: "relay_not_routed", обаждането endReason: "rejected"): контактът получава нов опит най-рано след минута (с политиката lorela_enterprise според нейния график), а след третия такъв опит подред отива за проверка с reviewReason: "call:relay_not_routed". Не се брои и обаждане, за което нашият гласов двигател никога не е съобщил и което сме приключили след два часа без съобщение като ненабрано и без цена (опитът има errorCode: "no_provider_report"): контактът се връща сред чакащите и получава нов опит най-рано след минута (с политиката lorela_enterprise според нейния график). Три неотчетени опита подред, дори смесени с опити relay_not_routed, пращат контакта за проверка с reviewReason според последния от тях, т.е. call:no_provider_report; контакти, които такова обаждане е пратило за проверка по-рано (call:failed, а с политика call:unknown), не се възобновяват сами. Без политика таванът важи само за автоматичните набирания: контакт, на който след изчерпване на опитите зададете resolve с action: "retry", получава още едно набиране отгоре. maxDurationSecs (30-300) е таванът на продължителността на ЕДНО обаждане, след който то автоматично се прекратява - продължителността по подразбиране е 120 секунди. Незадължителната политика lorela_enterprise се включва през API или MCP преди първия опит; съществуващите задачи не се променят сами. Вторият опит е най-рано 8 минути след началото на първия реален опит в часовете 08:00-22:00 Europe/Prague. Третият отива в следващия друг прозорец 08:00-09:00 или 17:00-19:00, четвъртият - в противоположния прозорец на следващия календарен ден. Винаги важат и callingWindow и неговите дни; след хоризонта за повторения политиката вече не набира: незадължителното retryMaxAgeDays е цяло число дни 1-30 (без задаване 5) и важи само с политиката. Хоризонтът свършва N × 24 часа след първия отчетен опит на контакта (твърди 24-часови дни, така че при смяна на часа местното време на края се измества с час). Може да се променя с PATCH и след началото на опитите (не при задача running или completed, която не може да се редактира): увеличаването при спряна задача връща контактите, отпаднали само заради хоризонта (reviewReason: "retry_age_expired"), обратно в състояние failed (чакат следващ опит) с нов nextAttemptAt, ако още имат свободен опит и най-близкият слот от графика попада в новия хоризонт и преди expiresAt; намаляването не отваря нищо. Отваря отново само PATCH, който увеличава хоризонта, затова изпращайте retryMaxAgeDays и удължения expiresAt в една заявка. Повтаря само no_answer, missed, busy, приключила гласова поща и вдигнато обаждане, в което набираният нищо не е казал (всичко без контакт с човек). Контакт с човек, отказ и грешка на двигателя спират автоматичното повтаряне; неясен резултат отива за проверка. Последният позволен опит (maxAttempts), който завърши с такъв повторяем резултат (невдигнато, заето, гласова поща или вдигнато обаждане, в което набираният нищо не е казал), приключва контакта като skipped с reviewReason: "retry_policy_exhausted" (както retry_age_expired след изтичане на хоризонта): няма какво да се проверява или повтаря. Неясен резултат от последния опит остава в review със същата причина. Без политика нищо не се променя: последният невдигнат опит си остава review. Проверено обратно обаждане от човек след изчерпване на опитите превежда контакта в completed. DNC, бюджетът и лимитите остават в сила: автоматичното блокиране след 3 неуспеха за 24 часа може да спре и четвъртия опит. При PATCH без maxAttempts досегашният лимит се запазва. С политиката ръчният resolve с action: "retry" връща грешка validation; позволени са само автоматично планираните ѝ опити. Изключение е възстановяването на доказано ненабран изтекъл claim преди първия реален опит: без активен работник, намерение за изпращане, идентификатор на обаждане при доставчика, резервация, цена или обратно извикване и само с доказани откази преди набирането в историята. Възстановяването запазва историята и ограниченията и връща контакта сред чакащите в спряна задача; само не набира. Напомняния не могат да се отварят отново по този начин. Ръчното повторение следователно не заобикаля четирите опита, хоризонта за повторения нито прекратяването след контакт с човек.
Глобална пропускателна способност
Набирането на всички задачи в ЦЯЛАТА платформа (не само във Вашия акаунт) минава през един cron, който работи на всеки 2 минути и обработва най-много 20 позиции на изпълнение - НО този таван се дели между едновременно работещите задачи, а не може да бъде изчерпан от една задача: от ВСЯКА активна задача при едно изпълнение се набира точно ЕДИН получател. Затова дори на съвсем празна платформа една задача никога не набира повече от един получател на 2 минути - сто получатели не приключват за ~20 минути, а за около 200 минути (100 x 2 минути). Планирайте според това времевия прозорец при кампании, чувствителни към времето (например appointment ден преди часа).
Ред за агента
Типичен ход в този ред:
- Агентът на задачата трябва да е ПУБЛИКУВАН, а публикуваната версия ТЕСТВАНА (
POST /v1/agents/{id}/draft/publish, послеPOST /v1/agents/{id}/simulate) - иначе по-късниятstartвръщаagent_not_ready. - По избор
POST /v1/tasks/csv-preview- проверява CSV на получателите, преди да се създаде задачата. POST /v1/tasks- създава задачата в състояниеdraft. Нищо не се набира.GET /v1/tasks/{id}- прочететеissues(проверка на сухо) и се уверете, че задачата е готова за пускане.- При нужда
PATCH /v1/tasks/{id}- променете правилата, ВИНАГИ сrevisionот последното четене. POST /v1/tasks/{id}/start- пуска набирането. Всяко вдигнато обаждане се таксува веднага.POST /v1/tasks/{id}/pauseпо всяко време по време на работа,POST /v1/tasks/{id}/startя възобновява.- След прекъсване (пауза по средата на обаждане, изтекъл claim, обаждане с още непозната цена или несигурно набиране, за което обаждането е намерено)
POST /v1/tasks/{id}/reconcileсверява състоянието с реалните обаждания; такава задача с останала работа завършва вpaused, дори някои контакти да чакат вreview, и може да се пусне отново чрезstart. Работеща задача и друга причина (variables_limit, неуспешна проверка на фактура или календар, несигурно набиране, за което обаждането не е намерено)reconcileне променя; контактите за проверка уреждайте чрезresolve. - Контакт, който е приключил за проверка (
items[].status: "review"), уредете сPOST /v1/tasks/{id}/items/{itemId}/resolveсaction: "retry"или"skip". При обичайна причинаretryвръща контакта сред чакащите, а задачата вpaused;skipго приключва и задачата преминава вpaused, ако остава работа, или вcompleted, ако всички контакти са приключени или пропуснати. Задача вpausedпосле възобновете сPOST /v1/tasks/{id}/start. - Когато контактът има
reviewReason: "dial:destination_auto_blocked", номерът е автоматично блокиран за 30 дни след многократно невдигнати обаждания и самиятretryне го отблокира - контактът веднага би се върнал вreview. Първо премахнете блокировката (POST /v1/dnc/{e164}/unblock, в MCPunblock_destination, номерът е вitems[].phone), послеresolveсaction: "retry". Приdial:on_dncпърво отстранете номера от списъка за недопускане на обаждания (DELETE /v1/dnc/{e164}), иначе пропуснете контакта. При собствен номер на акаунта, номер на друг акаунт във volai, невалиден номер, номер извън Чехия и Словакия и линия с повишена тарифа (dial:cannot_call_own_number,dial:cannot_call_volai_number,dial:invalid_number,dial:unsupported_country,dial:blocked_destination) нов опит не помага: използвайте самоskip. - Когато контактът има
reviewReason: "billing_unknown", първоначалното обаждане може вече да е протекло, само че цената му още не е позната. Първо извикайтеreconcileи проверете свързаното обаждане.retryзапомня, че контактът трябва да се опита отново, но ново обаждане не се позволява, докато цената на първоначалното не се установи; после задачата преминава вpausedи изисква новstart.skipпредотвратява ново обаждане; първоначалното обаждане остава свързано, а резервацията му продължава да се брои в бюджета, докато цената не се установи. Ако остава работа, следskipзадачата преминава направо вpausedи може да се пусне; без друга работа изчаква вneeds_attentionи след установяване на цената завършва вcompleted. Обаждане, което изобщо не е набирано (двигателят го е отхвърлил), никога не се таксува и се установява веднага на 0. - Контакт, който междувременно е купил или се е отписал, пропуснете без обаждане чрез
resolveсaction: "skip",reason: "customer_purchased"или"unsubscribed",revision, постояненoperationIdиevidenceRef, който сочи към документа за покупката или отписването (никога към телефон или имейл). Става приpendingконтакт вdraftзадача и приpending/failedвpausedзадача без неуредено обаждане; опитите, цените и списъкът за недопускане на обаждания се запазват.GET /v1/tasks/{id}после показва доказателството вitems[].resolution(reason,operationId,evidenceRef,resolvedAt); същото тяло може безопасно да се повтори, а другreasonилиevidenceRefза същия контакт е409 revision_conflict. Пропускането не записва номера в списъка за недопускане на обаждания: ако контактът не бива да бъде търсен повече, добавете го чрезPOST /v1/dnc. DELETE /v1/tasks/{id}накрая, ако задачата никога не е протекла или вече е приключила и искате записът да се изтрие.
Почти всяко записващо извикване (PATCH, start, pause, DELETE) взема revision от последното прочитане на задачата - същата оптимистична съвместимост като при чернови на агента. Несъответствие връща revision_conflict: заредете задачата отново (GET) и повторете с текущата revision. reconcile е изключение - revision там не е задължителна.
MCP
Същите инструменти като REST (list_tasks, get_task, create_task, update_task, pause_task, resolve_task_item, reconcile_task, start_task) - освен една разлика при пускането.
start_task потвърждава числата
MCP start_task взема допълнително confirmedRecipients и confirmedBudgetHal - те трябва да съвпадат точно с реалния брой получатели и бюджета на задачата, иначе връща validation с изписаните реални стойности и НИЩО не пуска. Така чужд AI агент, действащ по една неясно разбрана инструкция, не може по погрешка да стартира платена кампания с измислени числа - REST POST .../start няма този механизъм, защото там го извиква директно собственикът на акаунта със собствения си ключ.
delete_task и прегледът на CSV в MCP ги няма - изтриването остава в REST и в портала (необратимо действие с преписване на името), а прегледът на CSV е само стъпка от формуляра.
Грешки
task_not_found- В акаунта няма задача с тозиid.task_not_editable- Задачата работи или е приключила (running/completed), или еneeds_attentionбез възможност за възстановяване - правилата ѝ в момента не могат да се променят. Същия код връща иPOST .../items/{itemId}/resolveпри работеща задача: контакт вreviewсе появява още докато задачата набира останалите контакти и еrunning- изчакайте да премине вneeds_attentionили я спрете (POST .../pause).items_immutable- Списъкът с получатели не може да се замени, след като е проведен поне един опит за набиране или контакт е пропуснат сreason(покупка или отписване).budget_too_low- Бюджетът не покрива дори един опит с максимална продължителност на обаждането - увеличетеbudgetHalили намалетеmaxDurationSecs.task_not_startable- Задачата не е в състояниеdraft/ready/pausedили няма нито един чакащ получател.task_needs_attention- Преди следващото пускане е нуженPOST .../reconcile- нещо (версията на агента, двигателят) се е променило по време на работа.agent_not_ready- Черновата на агента или не е публикувана, или публикуваната версия не е тествана - публикувайте я (POST /v1/agents/{id}/draft/publish) и после тествайте публикуваната версия (POST /v1/agents/{id}/simulate) преди пускането.agent_version_changed- Конфигурацията на агента се е променила ПО ВРЕМЕ на работеща задача - тествайте и рестартирайте чрезreconcile.engine_required- Агентът на задачата не е на двигателя на volai (useForOutboundTasks: true) - изходящите кампании днес изискват двигателя, а не ElevenLabs.engine_contract_unavailable- Двигателят в момента не обявява поддръжка на променливи и ограничения за изходящи задачи - опитайте да пуснете отново по-късно.window_closed- Извън зададения времеви прозорец за обаждания - изчакайте отварянето или променетеcallingWindow.task_not_running- Пауза е възможна само при работеща задача.item_not_resolvable- Контактът не е в състояниеreview- решение (retry/skip) е възможно само за контакт, чакащ проверка, и то само при задача, която не работи. Изключение е пропускането сreason(customer_purchased,unsubscribed): то изисква неактивенpendingконтакт вdraftзадача илиpending/failedвpaused, без неуредено обаждане.task_not_deletable- Може да се изтрие само задача без позицияin_progressв състояниеdraft/ready/paused/completed/needs_attention.revision_conflict- Задачата междувременно се е променила - заредете я отново (GET) и повторете с текущатаrevision.
Пълната таблица с грешките за всяка крайна точка ще намерите в раздела Задачи в справочника за REST API.
Свързани
MCP сървър
Свържете Claude Code, Codex CLI, Codex desktop, Cursor и други AI редактори.
REST API
Пълна справка за всички крайни точки: номера, обаждания, SMS, мобилни номера за SMS, агенти и техните чернови, инструменти, записи, уебхукове, списък „не се обаждай“, relay, акаунт, задачи, кредит, документи, календари и интеграции.
Гласов агент
Системен промпт, инструменти, предаване на човек, записи и структурирани данни от обаждането.