Hane Platform
Workflows and cases
Workflow definitions, how cases start and their statuses, waits, schedules, and operating on cases.
This page explains how you define the way work proceeds as a workflow and drive each piece of work as a case. It also covers waits, schedules, and operations on cases.
Workflows and cases
Section titled “Workflows and cases”A workflow defines how a case proceeds, and a case is one piece of work driven by a workflow. Every case has exactly one business data record as its subject. For example, a “handle contract expiry” workflow drives one case per lease contract record.
You write a workflow as a workflows/v1alpha1 Workflow manifest.
apiVersion: workflows/v1alpha1kind: Workflowmetadata: name: lease-expiryspec: case: purpose: Decide how to handle the end of the contract subject: LeaseContract # type of the case subject title: '"Expiry: " + subject.contract_no' businessKey: subject.contract_no # never create two cases with the same key deadline: subject.notice_due attention: [end_date, notice_due] # flag on the case while not confirmed start: check-values steps: check-values: branch: cases: - when: 'states.end_date != "confirmed"' next: confirm-dates default: decide confirm-dates: task: title: '"Check the end date: " + subject.contract_no' assignment: fleet-desk # name of an AssignmentRule due: "addDays(subject.notice_due, -30)" outcomes: { confirmed: Checked and confirmed } on: { confirmed: decide } decide: task: title: '"Decide on renewal: " + subject.contract_no' assignment: fleet-desk due: subject.notice_due outcomes: { renew: Renew the lease, return: Return the vehicle } on: { renew: done-renew, return: done-return } done-renew: complete: { outcome: renew } done-return: complete: { outcome: return }Conditions, titles, and other expressions are written in CEL. Expressions can use the subject record (subject) and its value states (states), the case (case), the results of earlier steps (steps), and the case input (input).
Step types
Section titled “Step types”| Step | What it does |
|---|---|
task |
Creates a task, assigns it, and waits for it to close. Proceeds according to the outcome (one of outcomes) |
notify |
Sends a notification, such as an email, to the assignees or to an assignment rule’s group |
branch |
Chooses the next step by CEL conditions |
agent |
Runs an agent and proceeds according to its result. If the agent fails or is stopped, goes to on.failed |
wait |
Waits for an event, the result of an operation an agent proposed, a document to arrive, email replies, or time |
record |
Looks up a business data record by key and creates it if missing or updates it if present. Values are estimated, and the source is the case and step |
query |
Follows relations by ID from the subject record and makes the result available to later steps |
escalate |
Creates a task to hand the case over and ends the case when it closes |
complete |
Completes the case and records its outcome (outcome) |
How cases start
Section titled “How cases start”Cases start from the following places. In every case, a case starts with its subject record and the workflow in the active release at that time.
- Schedules: At a set time every day, start a case for each record that matches a condition (see “Schedules” below).
- Agents: An agent starts a workflow listed under
workflowsin its definition with theworkflow.starttool. - Document inquiries: When a value cannot be read from a document and is set to pending inquiry, the inquiry workflow named in the extraction definition starts.
If a case with the same business key (businessKey) is in progress, no new case is created.
Case statuses
Section titled “Case statuses”| Status | Meaning |
|---|---|
running |
Advancing through steps |
waiting |
Waiting for a task, an event, the result of an operation, and so on |
completed |
Reached a complete step and finished |
cancelled |
Cancelled |
failed |
A step failed. The reason is kept in error and in the history |
GET /v1/workflows/cases/{id} returns the case together with its history (events per step), its waits, and the workflow definition it runs on. The case’s attention lists the values among case.attention that are not confirmed.
While a case waits, Hane runs nothing for it. It does not keep calling an LLM or keep an agent’s CLI around. The wait condition is saved, and the case resumes when a task closes, an event arrives, or a deadline passes.
| What to wait for | How to write it |
|---|---|
| A task | A task step. After timeout (in the form 30m, 72h, 7d), the task is cancelled and the case goes to on.expired. With closeOn, the task can be closed without waiting for a person when a given event arrives |
| An event | wait.event and wait.match (CEL). Waits until a matching event arrives |
| An operation an agent proposed | wait.action. You must write all seven destinations: the results of approval and execution (succeeded, failed, cancelled, expired, and so on) and timeout |
| A document | wait.document. Waits until a document of the given type linked to the subject record arrives |
| Email replies | wait.replies. Waits until every sent email has a reply or is known not to get one |
Any form of wait can have a timeout, and a timeout goes to on.timeout. A timeout never cancels or resends a proposed operation on its own.
Schedules
Section titled “Schedules”A schedule is written as a workflows/v1alpha1 Schedule manifest and fires at a set time every day. When it fires it does one of three things.
| Written as | What happens when it fires |
|---|---|
workflow and forEach |
Starts a case for each record of type forEach.type that matches forEach.where (CEL) |
agent |
Runs an agent once. Its input is the firing date and the schedule name |
connection |
Starts one import from an external connection |
apiVersion: workflows/v1alpha1kind: Schedulemetadata: name: daily-expiry-scanspec: every: day at: "07:00" timezone: Asia/Tokyo forEach: type: LeaseContract where: 'record.status == "active" && record.notice_due != null && daysBetween(event.date, record.notice_due) <= 90' workflow: lease-expirySchedules are registered again whenever a ReleaseBundle is activated. Each firing uses the active release at that moment.
| Operation | API |
|---|---|
| List schedules and their next firing time | GET /v1/workflows/schedules |
| Trigger manually (the firing date is today) | POST /v1/workflows/schedules/{name}/trigger |
| Pause and resume | POST /v1/workflows/schedules/{name}/pause, resume |
Each firing records how many records matched, how many cases were created, how many already existed, and which records failed and why.
Operating on cases
Section titled “Operating on cases”Operate on failed cases or cases you want to stop through the API or the Console. These operations require the workflows:operate scope.
| Operation | API | What it does |
|---|---|---|
| List | GET /v1/workflows/cases |
Filter by status, workflow, subject_id, and business_key |
| Cancel | POST /v1/workflows/cases/{id}/cancel |
Requires a reason. Also cancels the case’s open tasks |
| Retry | POST /v1/workflows/cases/{id}/retry |
Retries a failed case from the step that failed |
| Restart | POST /v1/workflows/cases/{id}/restart |
Cancels the current case and starts a new one with the same workflow and subject record on the current active release |
When a case finishes at a complete step, one outcome record is written. Read outcome records with GET /v1/workflows/outcomes. There is only one outcome record per case and completion criterion, so redelivered events never add more.
Case completion, failure, and cancellation can be received through webhooks as the events workflows.case.completed, workflows.case.failed, and workflows.case.cancelled.