Reply Pilot Backend
Tato stranka popisuje modul reply-pilot-be/.
Role modulu
- vlastni JSON API pro inbox a komunikacni workflow
- vlastni lokalni snapshot schranky a inbox cache
- vola
reply-pilot-gmailpro Gmail sync a drafty - pri zobrazeni inboxu/detailu threadu udrzuje komunikacni historii v
reply-pilot-db - vlastni OpenAI debug/generation flow pro
reply-pilot-app - vlastni server-side lead import workflow pro JSONL batch soubory
- je hlavni backend owner e-mailove vrstvy
Runtime
- bezi jako samostatny Flask/Gunicorn kontejner
- zapisuje do
reply-pilot-be/dataareply-pilot-be/logs conf/zustava read-only mount- na interni siti se hlasi jako
reply-pilot-be reply-pilot-appareply-pilot-workerho volaji preshttp://reply-pilot-be:5000- Gmail sluzbu vola pres
GMAIL_API_BASE_URL, defaultnehttp://reply-pilot-gmail:5000 - PostgreSQL vola pres
reply-pilot-dbna interni siti
Email Artifact Flow
Import emailu probiha ve trech vrstvach:
- Gmail sync vytvori thread snapshot v
reply-pilot-be/data/emails/threads/a pri dostupnych prilohach stahne binarky doreply-pilot-be/data/emails/attachments/. - Activity import zapise do PostgreSQL:
activity+activity_emailactivity_email_attachmentjako DB metadata nad lokalni file cacheactivity_email_linkjako explicitni URL nalezene vbody_text- Pozdejsi attachment phase muze dotahnout chybejici binarky; backend pak
znovu synchronizuje
activity_email_attachment, aby DB metadata odpovidala aktualni lokalni cache.
Dulezite pravidlo:
- PostgreSQL je source of truth pro attachment metadata a pro nalezene URL
- binarni obsah priloh zustava v backend file cache
- vazba z DB na file cache vede pres
activity_email_attachment.relative_path - odeslane e-maily se po uspesnem Gmail
sendmaterializuji stejnouActivityImportStorecestou jako importovane zpravy; lead import wizard pri akci odeslat+a importovat posila e-mail v backendu, aby se pred zapisemactivity_emailnejdriv zalozila firma a kontaktni vazby
Lead Import Runtime
Lead import flow cte serverove JSONL soubory z backend storage, typicky pod
reply-pilot-be/data/lead-imports/:
inbox/ceka na operatoraprocessing/drzi soubor navazany na aktivni review batchdone/drzi dokoncene batch souboryfailed/drzi soubory, ktere nesly nacist nebo zalozit do DB
Backend:
- vypise dostupne soubory pro web app
- ze zvoleneho souboru zalozi
lead_import_batchalead_import_item - pri otevreni detailu polozky umi vygenerovat AI draft prvniho osloveni
- pri operatorove akci umi zalozit nebo doplnit firmu, odeslat prvni osloveni,
ulozit odeslany e-mail do kontaktni historie, ulozit
activity_note, propsatparty_outreach_policya vytvorit Jira task
Manual Company Create
Backend exposeuje POST /api/companies pro rucni zalozeni firmy z web appky.
Endpoint v jedne transakci zalozi pouze organizaci nad existujicim party modelem.
Kontakty, osoby, poznamky, outreach policy ani Jira tasky nejsou soucasti tohoto
V1 formulare.
V1 request obsahuje:
company:display_name,legal_name,company_registration_number,tax_identifier,website,roles,show_by_default
Pred insertem backend kontroluje duplicity podle presneho ICO, DIC a
DOMAIN/WEBSITE identifikatoru. Pri nalezu vraci 409 s kandidaty a zadny
zaznam neuklada.
Email Thread Reply Tasky
Backend vlastni vytvareni Jira tasku typu Email Thread Reply.
- UI vola
POST /api/email-threads/<email_id>/reply-taskssparty_id,assignee_user_id,summaryadescription. - Backend nacita e-mailove vlakno ze sve e-mail sluzby, kontroluje duplicitu pres
task_jira_email_thread_reply.external_thread_id, vytvari Jira issue typuJIRA_DEFAULT_ISSUE_TYPE_REPLY_EMAILa uklada existujici lokalni tabulkytask,task_jiraatask_jira_email_thread_reply. - Do Jira description doplnuje link na detail firmy a po lokalnim ulozeni i link
na detail tasku podle
APP_PUBLIC_BASE_URL. - Pri duplicitnim threadu endpoint vraci
409a metadata existujiciho tasku, aby app mohla presmerovat na jiz zalozeny task.
Activity import pri nove prichozi zprave od externiho dodavatele nejdriv preklopi
existujici reply task do stavu Drafting Reply. Kdyz pro thread reply task jeste
neni a firma ma Supplier Onboarding task, backend zalozi novy Email Thread
Reply, prevezme assignee z onboarding tasku a novy Jira ticket take prevede do
Drafting Reply. V1 nepridava primou DB vazbu reply task -> onboarding task;
vztah se odvozuje pres stejnou firmu (task_jira.party_id) a e-mailove vlakno.
AI Evidence Output Contract
Pro budouci AI klasifikaci requirement evidence jsou source of truth tyto JSON schema soubory:
reply-pilot-be/default-conf/ai-schemas/enlistment-table.schema.jsonreply-pilot-be/default-conf/ai-schemas/feed.schema.jsonreply-pilot-be/default-conf/ai-schemas/supplier-identifier.schema.json
Spolecna pravidla:
- vsechny vystupy musi projit validaci proti schema pred zapisem do DB
additionalPropertiesjsou vsude zakazane, aby backend nemusel resit tichy driftevidence_keyafact_keymusi byt unikatni v ramci jedne AI odpovediconfidenceje vzdy0..1model_name,model_versionaprompt_versionse neberou z AI payloadu; doplnuje je backend pri zapisuextract_jsonma ukladat validovany fragment, ktery vedl ke vzniku konkretniho DB radku, ne jen volny textovy summary
AI Classification Runtime
reply-pilot-be exposeuje worker endpoint POST /api/requirements/ai-classify/run.
Tenhle job:
- vybira jen emaily, ktere uz prosly deterministic prefiltrem
- scope
ENLISTMENT_TABLEbere zparty_requirement_evidencescreated_by = deterministic-enlistment-detector - scope
FEEDbere zparty_feed_factscreated_by = deterministic-email-parser - scope
SUPPLIER_IDENTIFIERbere zparty_supplier_identifier_factscreated_by = deterministic-email-parser - AI job znovu nepousti kandidaty, ktere uz maji AI materializovane radky s
created_by = ai-requirement-classifier - pri chybe jedne AI klasifikace backend zaloguje chybu, preskoci konkretni email a pokracuje dalsim kandidatem
Structured output validace:
- backend posila do OpenAI commitnute JSON schema z
default-conf/ai-schemas/ - OpenAI schema drzi jen subset kompatibilni s Responses API; podminena pravidla
typu
EMAIL_ATTACHMENT => attachment_* povinneneboDIRECT_URL => url_* povinnehlida nasledna backend validace - po odpovedi dela vlastni strict validaci fixnich payload shape pravidel, bez runtime dependency na externi
jsonschemaknihovne - az po uspesne validaci zapisuje DB evidence/facts
Requirement Aggregation Runtime
reply-pilot-be exposeuje i worker endpoint POST /api/requirements/evaluate/run.
Tenhle job:
- cte
party_requirement_eval_queue - claimuje pending polozky pres
FOR UPDATE SKIP LOCKED - pro
ENLISTMENT_TABLEagreguje historickeparty_requirement_evidence - pro
FEEDagreguje historickeparty_requirement_evidenceaparty_feed_fact - pro
SUPPLIER_IDENTIFIERagreguje historickeparty_supplier_identifier_fact - vysledek zapisuje do
party_requirement_state - pro
FEEDpropaguje i finalniresolved_delivery_mode_codeafeed_url - pro
SUPPLIER_IDENTIFIERpropagujeresolved_value_type_codea hodnotu - pri manualnim override radek v
party_requirement_stateneprepisuje - pri chybe jedne queue polozky ji jen odlozi na pozdeji a zpracovani dalsich firem pokracuje
- kdyz se zmeni
REQUIREMENT_AGGREGATION_RULESET_VERSION, backend jednorazove znovu zaqueueuje vsechny firmy doparty_requirement_eval_queue
Historical Requirement Backfill
Pro jednorazovy nebo strankovany backfill historickych threadu exposeuje backend
endpoint POST /api/requirements/backfill/run.
Tenhle job:
- umi zpracovat jednu firmu pres
party_idnebo strankovanou davku presafter_party_id+limit - nejdriv znovu synchronizuje deterministic email artifacts a extracted facts nad historickymi thready dane firmy
- preferuje thread snapshot z backend cache; kdyz chybi, spadne na DB-only fallback nad
activity_emailaactivity_email_attachment - AI klasifikaci i requirement agregaci pousti jen nad vybranou sadou firem, ne globalne nad celou frontou
- je idempotentni, protoze deterministic vrstvy delaji replace svych radku a agregace bezi pres existujici queue/upsert model
- vraci operativni report poctu firem, threadu, synchronizovanych zprav, AI kandidatu a prepoctenych atributu
AI prompt refresh:
- AI candidate scan bere v uvahu aktualni
REQUIREMENT_AI_PROMPT_VERSION - pokud pro email existuji jen starsi AI radky s jinou prompt verzi, backend je povazuje za stale a zaradi email znovu do AI klasifikace
ENLISTMENT_TABLE
Schema:
- top-level
summary - pole
evidence_items - kazdy
evidence_itemreprezentuje jeden kandidátní dukaz
Mapovani do DB:
- pro kazdy
evidence_itemvytvor jeden radek vparty_requirement_evidence requirement_code = 'ENLISTMENT_TABLE'source_type_code,verdict_code,confidence,reasonse berou primo z itemuactivity_email_idaexternal_thread_iddoplni backend z aktualniho importovaneho emailu- pokud je
source_type_code = 'EMAIL_ATTACHMENT', backend preneseattachment_filename,attachment_relative_patha volitelneattachment_sha256 - pokud je
source_type_code = 'EMAIL_MESSAGE', attachment sloupce zustanou prazdne extract_jsonna evidence radku ma obsahovat presnyevidence_itema volitelne i top-levelsummary- top-level
summaryse nezapisuje primo doparty_requirement_state; slouzi jako vstup pro pozdejsi agregacni worker
FEED
Schema:
- top-level
summary - pole
evidence_items - pole
feed_facts - kazdy
feed_factodkazuje na jedenevidence_itempresevidence_key
Mapovani do DB:
evidence_itemsse materializuji doparty_requirement_evidencerequirement_code = 'FEED'- backend si vytvori mapu
evidence_key -> party_requirement_evidence.id - pro kazdy
feed_factvytvori jeden radek vparty_feed_fact evidence_idse naplni zevidence_key; kdyz reference chybi nebo ukazuje na neexistujici key, cely AI payload se ma povazovat za nevalidnidelivery_mode_code,url_raw,url_normalized,confidence,reasonse berou primo z factu- pri
delivery_mode_codeDIRECT_URLneboLOGIN_REQUIREDmusi byt vyplneneurl_rawiurl_normalized - pri
IDENTIFIER_ONLY,MANUAL_EXPORT,NO_FEEDneboOTHERmohou byt URL prazdne - attachment metadata se do
party_feed_factkopiruji z navazanehoevidence_item; kdyz je zdrojemEMAIL_MESSAGE, zustanou attachment sloupce prazdne extract_jsonna fact radku ma obsahovat konkretnifeed_fact;extract_jsonna evidence radku konkretnievidence_item
SUPPLIER_IDENTIFIER
Schema:
- top-level
summary - pole
evidence_items - pole
identifier_facts - kazdy
identifier_factodkazuje na jedenevidence_itempresevidence_key
Mapovani do DB:
- v aktualnim schema V1 se
SUPPLIER_IDENTIFIERnematerializuje doparty_requirement_evidence, protozerequirement_typezatim nema odpovidajici kod - backend proto validuje
evidence_items, ale do DB zapisuje jenparty_supplier_identifier_fact evidence_keyslouzi jako interní most pro kopirovani source metadata zevidence_itemsdo fact radkuidentifier_type_code,value_raw,value_normalized,confidence,reasonse berou primo zidentifier_factevidence_idzustavaNULLattachment_filename,attachment_relative_pathaattachment_sha256se kopiruji z navazanehoevidence_item, pokud je zdroj attachmentextract_jsonna fact radku ma obsahovat konkretniidentifier_facta volitelne odkaz na pouzityevidence_item- pokud se pozdeji prida
requirement_typepro identifikatory dodavatele, schema neni potreba menit; backend jen zacneevidence_itemsmaterializovat i doparty_requirement_evidence
Endpointy
GET /healthzGET /api/metaGET /api/inboxGET /api/emailsGET /api/emails/<email_id>GET /api/emails/<email_id>/attachmentsPOST /api/email-threads/<email_id>/reply-tasksPOST /api/companiesPOST /api/peoplePATCH /api/people/<party_id>POST /api/parties/<party_id>/contactsPATCH /api/parties/<party_id>/contacts/<contact_mech_id>DELETE /api/parties/<party_id>/contacts/<contact_mech_id>POST /api/companies/<party_id>/identifiersDELETE /api/companies/<party_id>/identifiers/<identifier_id>DELETE /api/companies/<company_id>/people/<person_id>POST /api/mailbox/importGET /api/mailbox/import/statusPOST /api/mailbox/import/stepPOST /api/cme/company-check/runGET /api/lead-imports/filesPOST /api/lead-imports/batchesGET /api/lead-imports/batches/<batch_id>GET /api/lead-imports/batches/<batch_id>/items/<item_id>POST /api/lead-imports/batches/<batch_id>/items/<item_id>/actionsPOST /api/requirements/ai-classify/runPOST /api/requirements/evaluate/runPOST /api/requirements/backfill/runPOST /api/emails/<email_id>/drafts/replyPOST /api/emails/<email_id>/send/replyPOST /api/emails/<email_id>/debug/generate
Reply draft/send endpointy prijimaji puvodni JSON payload bez priloh. Pokud odpoved obsahuje prilohy, klient posila multipart/form-data se stejnymi textovymi poli recipient, subject, body_text, reply_to_message_id a opakovanym file polem attachments. Limit je 10 souboru, 10 MB na soubor a 20 MB celkem.
Party Mutation API
Backend exposeuje rucni mutace pro osoby, kontakty, identifikace a vazby nad existujicim party/contact modelem. Vsechny mutace bezi v jedne DB transakci a overuji, ze cilova party existuje, neni mergnuta a ma ocekavany typ.
POST /api/peoplezalozi osobu a volitelne ji navaze na firmu presCONTACT_FOR.PATCH /api/people/<party_id>upravi zakladni identitu osoby.POST/PATCH/DELETE /api/parties/<party_id>/contacts...spravuje aktivni vazbu party naEMAILneboPHONEcontact mechanism.DELETEkontaktu nastavujeparty_contact_mech.thru_date;contact_mechani historie aktivit se nemazou.POST /api/companies/<party_id>/identifierspodporujeWEBSITE,DOMAIN,GLN,VENDOR_CODEaEXTERNAL_ID; ICO/DIC zustavaji v editaci firmy.DELETE /api/companies/<party_id>/identifiers/<identifier_id>mazeparty_identifier, protoze tabulka nema lifecycle sloupec.DELETE /api/companies/<company_id>/people/<person_id>ukonci aktivniCONTACT_FORvztah presthru_date; osoba zustava zachovana.
Chyby vraci JSON se status: error a reason. Validacni chyby pouzivaji
400, konflikt duplicit 409 s volitelnymi candidates, chybejici zaznam
404 a nenakonfigurovana DB 503.