flowinquiry v1examples/inquiry/temporal/inquiry.flow · dandori doc
Jev picks the kind of a customer's inquiry and says how sure it is; an agent reads the inquiry for an order number and its point, and for its kind too, which the flow takes when Jev is not sure enough of its own. A rule decides the desk that takes it and how soon it is answered; another agent drafts the first reply; and a ticket goes into the desk's system. Jev picks, agents read and write (a model the company runs itself reads, Claude writes), and the rule decides. Written for Temporal: Jev and the agents are activities dandori writes, Jev called with TypeSafe's key (TYPESAFE_API_KEY), the reading sent to the company's Ollama, which serves Open Responses (`url`), and the draft to Claude with the key the worker has; the rule runs in the worker of the workflow as a local activity, its answer kept in the history as a marker; and filing the ticket is an activity you write
flow| Line | Call | Calls | Retries | Timeout | When it fails |
|---|---|---|---|---|---|
| 62 | reading = read_inquiry(…) | agent · gpt-oss:20b · http://ollama.internal:11434/v1 | 2 times every 10 seconds (failure, timeout) | 1 minute | timeout, failure → line 63 |
| 64 | by_hand = file_ticket(…) | a task you write, key | 2 times every 5 seconds (failure, timeout) | — | timeout, failure → the workflow fails |
| 67 | kind = pick_kind(…) | jev · jev-1.13.0 · confidence 0.8 else unsure | 2 times every 1 second (failure, timeout) | 10 seconds | unsure, timeout, failure → line 68 |
| 69 | decision = routing(…) | rule inquiry_routing.rule, a local activity on Temporal | 2 times, after 1 second and 2 (failure) | — | timeout, failure → the workflow fails |
| 74 | draft = draft_reply(…) | agent claude · claude-sonnet-5 | — | 1 minute | timeout, failure → line 75 |
| 76 | t = file_ticket(…) | a task you write, key | 2 times every 5 seconds (failure, timeout) | — | timeout, failure → the workflow fails |
| Line | End |
|---|---|
| 65 | succeed ticket_id = by_hand.ticket_id, desk = general |
| 77 | succeed ticket_id = t.ticket_id, desk = decision.desk |
Pick a step to see what the checker knows there. Pick a scenario on the left to light up the way its run goes; the number beside a step is how often the run passes it.
inquiry v1Jev picks the kind of a customer's inquiry and says how sure it is; an agent reads the inquiry for an order number and its point, and for its kind too, which the flow takes when Jev is not sure enough of its own. A rule decides the desk that takes it and how soon it is answered; another agent drafts the first reply; and a ticket goes into the desk's system. Jev picks, agents read and write (a model the company runs itself reads, Claude writes), and the rule decides. Written for Temporal: Jev and the agents are activities dandori writes, Jev called with TypeSafe's key (TYPESAFE_API_KEY), the reading sent to the company's Ollama, which serves Open Responses (`url`), and the draft to Claude with the key the worker has; the rule runs in the worker of the workflow as a local activity, its answer kept in the history as a marker; and filing the ticket is an activity you write
inquiry: Inquiryticket_id: string, desk: routing.deskexamples/inquiry/temporal/inquiry.flowreading = read_inquiry(…) line 6262 let reading = read_inquiry(text: inquiry.text) 63 on failure =>
agent · gpt-oss:20b · http://ollama.internal:11434/v1timeout, failure → line 6339 # A model on the company's own Ollama reads the text, through Open Responses; the schema of 40 # Reading holds its answer to one of the rule's kinds. 41 task read_inquiry(text: string) -> Reading 42 agent "Read the text of a customer's inquiry, choose its kind, take out the order number if one is written, and sum up its point in one sentence. If no order number is written, give null." 43 model "gpt-oss:20b" 44 effort low 45 url "http://ollama.internal:11434/v1" 46 plaintext "The model server is reached only inside the cluster network, which the service mesh encrypts" 47 timeout 60 seconds 48 retry 2 times every 10 seconds
by_hand = file_ticket(…) line 64 64 let by_hand = file_ticket(inquiry_id: inquiry.id, desk: general, within: 24, subject: "An inquiry that could not be read", text: inquiry.text, draft: none)
keytimeout, failure → the workflow fails56 # The ticket goes into the desk's system through its client library, in code you write. 57 task file_ticket(inquiry_id: string, desk: routing.desk, within: duration[h], subject: string, text: string, draft: string?) -> Ticket 58 key 59 retry 2 times every 5 seconds
succeed ticket_id = by_hand.ticket_id, desk = general line 65 65 succeed ticket_id = by_hand.ticket_id, desk = general
kind = pick_kind(…) line 6767 let kind = pick_kind(text: inquiry.text) 68 on unsure, failure => let kind = reading.kind
jev · jev-1.13.0 · confidence 0.8 else unsureunsure, timeout, failure → line 6827 # Jev picks one of the rule's kinds, knowing what each means, and says how sure it is. 28 task pick_kind(text: string) -> routing.kind 29 jev "Which kind of inquiry is this?" 30 returns "The customer wants to send an item back or exchange it" 31 delivery "A parcel is late, lost or damaged, or the customer asks where it is" 32 billing "A charge, an invoice, a payment or a refund" 33 other "None of the above" 34 model "jev-1.13.0" 35 confidence 0.8 else unsure 36 timeout 10 seconds 37 retry 2 times every 1 second
let kind = reading.kind line 68 68 on unsure, failure => let kind = reading.kind
decision = routing(…) line 69 69 let decision = routing(kind: kind, member: inquiry.member)
inquiry_routing.rule, a local activity on Temporaltimeout, failure → the workflow fails4 use rule routing from "../rules/inquiry_routing.rule" 5 local
let subject = "An inquiry about {kind}" line 70 70 let subject = "An inquiry about {kind}"
match reading.order_id line 7171 match reading.order_id 72 some order_id => let subject = "An inquiry about {kind} (order {order_id})" 73 none => pass
let subject = "An inquiry about {kind} (order {order_id… line 72 72 some order_id => let subject = "An inquiry about {kind} (order {order_id})"
draft = draft_reply(…) line 7474 let draft = draft_reply(kind: kind, point: reading.point, order_id: reading.order_id, within: decision.within) 75 on failure => let draft: string? = none
agent claude · claude-sonnet-5timeout, failure → line 7550 task draft_reply(kind: routing.kind, point: string, order_id: string?, within: duration[h]) -> string 51 agent claude "Draft the first reply to the inquiry, politely, in three sentences at most. `within` is the number of hours before the reply is due. Promise nothing that cannot be kept." 52 model "claude-sonnet-5" 53 effort medium 54 timeout 60 seconds
let draft = none line 75 75 on failure => let draft: string? = none
t = file_ticket(…) line 76 76 let t = file_ticket(inquiry_id: inquiry.id, desk: decision.desk, within: decision.within, subject: subject, text: inquiry.text, draft: draft)
keytimeout, failure → the workflow fails56 # The ticket goes into the desk's system through its client library, in code you write. 57 task file_ticket(inquiry_id: string, desk: routing.desk, within: duration[h], subject: string, text: string, draft: string?) -> Ticket 58 key 59 retry 2 times every 5 seconds
succeed ticket_id = t.ticket_id, desk = decision.desk line 77 77 succeed ticket_id = t.ticket_id, desk = decision.desk
end: succeedsThe flow runs to its end, and the workflow succeeds.
reading = read_inquiry(…) okkind = pick_kind(…) okdecision = routing(…) oklet subject = "An inquiry about {kind}"match reading.order_id → nonedraft = draft_reply(…) okt = file_ticket(…) oksucceed ticket_id = t.ticket_id, desk = decision.deskreading = read_inquiry(…) failure failure failure → on failureby_hand = file_ticket(…) oksucceed ticket_id = by_hand.ticket_id, desk = generalreading = read_inquiry(…) failure failure failure → on failureby_hand = file_ticket(…) failure failure failure → not handled herereading = read_inquiry(…) failure okkind = pick_kind(…) ok → on unsure, failurelet kind = reading.kinddecision = routing(…) failure failure failure → not handled herereading = read_inquiry(…) okreading = read_inquiry(…) okkind = pick_kind(…) ok → on unsure, failurelet kind = reading.kinddecision = routing(…) okreading = read_inquiry(…) okkind = pick_kind(…) failure okdecision = routing(…) okreading = read_inquiry(…) okkind = pick_kind(…) okreading = read_inquiry(…) okkind = pick_kind(…) okdecision = routing(…) oklet subject = "An inquiry about {kind}"match reading.order_id → some order_idlet subject = "An inquiry about {kind} (order {order_id…draft = draft_reply(…) failure → on failurelet draft = nonet = file_ticket(…) failure failure failure → not handled herereading = read_inquiry(…) okkind = pick_kind(…) okdecision = routing(…) oklet subject = "An inquiry about {kind}"match reading.order_id → nonedraft = draft_reply(…) failure → on failurelet draft = nonet = file_ticket(…) failure oksucceed ticket_id = t.ticket_id, desk = decision.deskreading = read_inquiry(…) okkind = pick_kind(…) okdecision = routing(…) oklet subject = "An inquiry about {kind}"match reading.order_id → nonedraft = draft_reply(…) okreading = read_inquiry(…) okkind = pick_kind(…) okdecision = routing(…) oklet subject = "An inquiry about {kind}"match reading.order_id → nonedraft = draft_reply(…) okt = file_ticket(…) okreading = read_inquiry(…) failure failure failure → on failureby_hand = file_ticket(…) failure oksucceed ticket_id = by_hand.ticket_id, desk = generalreading = read_inquiry(…) failure failure failure → on failureby_hand = file_ticket(…) ok