Guided Business Tasks¶
A task is a recorded screen flow with named inputs and a named answer. Someone who knows the business question — but not the application — fills in a short form and reads the result, without navigating a green screen.
The whole life of a task, in one take — record a flow, name its inputs, mark the answer, run it and read the result:
Account balance enquiry
Retrieves the current cleared balance for a customer account.
Account number [ 40218855 ] required, 8 digits
As-at date [ 2026-08-08 ] optional
[ Back ] [ Run ]
3270Web drives the application, then shows a result card:
Account balance enquiry 2.4 s
Account 40218855
Name J MARGOLIS
Cleared balance 1,240.55
Available 1,190.55
[ Copy ] [ CSV ] [ Run again ] [ Close ]
Running a task¶
Open Tasks from the menu bar (the labelled button on the right) or the command palette. Tasks are business-user surface, so the control stays visible in Business mode.
Pick a task, fill in the form, press Run. The dialog closes and a card
appears in the corner — the terminal stays visible the whole time. That
is deliberate: operators need to see what the host is actually doing, and it
is how trust in the automation gets built. The card never covers the
Operator Information Area,
so X SYSTEM and the operator-error indicator stay readable.
Cancel stops the run. The terminal is left exactly where it stopped — the request was to stop the automation, not to undo it, and a 3270 transaction cannot be rolled back.
A run lives on the server, so reloading the page does not lose it; the card reappears and carries on reporting.
When a task does not finish¶
A task stops at the first step whose screen is not what it expected, and reports:
- which step it stopped at, and why
- what it expected against what it found at that position
- the screen it stopped on, behind a disclosure
The terminal is left on that screen so you can take over by hand.
This is the opposite of what recording playback does, on purpose. Playback logs a failed step and carries on, which suits a scripted regression. For a business transaction, carrying on means typing an account number into whatever field happens to be under the cursor on a screen nobody expected. An output that cannot be read counts as a failure too, unless it is marked optional — a result card showing a blank balance is worse than an honest error.
Defining a task¶
From a recording (the wizard)¶
Record the flow once, then press Save recording as a task on the recording controls — or find it in the command palette. The wizard is five stages, in the shape of the task itself:
- Details. What the task is called and what it does. The name is what appears on the menu, and what an assistant calls to run it.
- Inputs. Everything typed during the recording arrives as an input the operator will be asked for, labelled with the text the screen itself uses. Each one is Ask the operator, Always this value — which removes it from the form and bakes the value into the step — or Ask, and never store it, for a secret. Behind Validation and hint are the pattern, the maximum length and the hint shown under the field.
- Steps. The guard on each step, shown against the screen that step was recorded on. Drag on the screen to guard on different text, pick from the shortlist of what else that screen offers, tick must NOT be there to guard against an error line, or type a row, column and text directly. A step with no guard is marked as such — it will act on whatever screen the terminal is showing.
- The answer. Click a value on the screen the flow ended on, or drag across it, to mark what the task reports back. This is the one thing a recording cannot work out for itself. Each marked region can be adjusted by row, column and width, given a pattern to extract from, or marked as one that may be missing.
- Review. The server validates the task and reads the answer back from the screen — using the same validation and the same extraction the runner uses, so what it shows is what a run will do. Then save.
On the first stage is What was assumed — every guess the draft made, listed rather than buried. Read it: a guard that could not be derived, a field with no label, or a value that was cleared rather than typed all show up there.
Marked regions extend to the next text on the row
If you mark ADA you get a region as wide as the slot the value sits
in, not as wide as those three characters. That is deliberate — a region
sized to the recorded value would silently truncate a longer one, so
GRACE would come back as GRA. Trailing spaces are trimmed from the
result.
A recorded password is never stored
A recording of a sign-on carries the password that was typed. A field whose label names a secret — password, passcode, PIN, API key — arrives marked Ask, and never store it: masked on the form, absent from the catalogue file, and kept out of every result and log line. The host still receives it; nothing else does. Clear the mark if the field is not a secret, and set it yourself on one whose label does not say so.
Changing a task¶
Open Tasks, pick the task, and press Edit. The same five stages come back with the saved task in them, and saving replaces it.
A correction that costs a re-recording of the whole flow does not get made, and a catalogue nobody dares touch is worse than one that is a little wrong. The screen offered for re-marking the answer is whatever the terminal is showing now — the wizard says so rather than implying it is the screen the task ends on — and every region can be edited as a row, a column and a width regardless of where the terminal happens to be.
Renaming a task saves it as a new one and leaves the old one in place; the Review stage says so before you save.
Where a task can be run from¶
The Review stage ends with Where this task can be run from, because a task is not only a menu entry. The same document is:
- an entry on the Tasks menu for anyone with a session;
- an MCP tool of its own,
task_<name>, offered to an assistant with a schema built from the inputs — see MCP Server. The Review stage gives the generated tool name, and says so when another task would collide with it; - an operation on the token-authenticated REST API, with the request shown ready to copy;
- content an extension can ship to another deployment, alongside the skills that explain when to use it.
From a chaos run¶
A chaos exploration maps an application's screens and the
fields that drive them, and a business function names one path through
that map. GET /chaos/business/task-draft?name=... converts one into a task
draft — or every function at once if you omit the name.
This is the join between exploration and use: the mind-map is the asset, the task is the product.
The conversion has one real difficulty, and it is worth knowing about. Chaos identifies a screen by hash, which is exact and useless to a person: when it stops matching, all it can say is "a different screen". A task guards with positional text from the screen's own labels. The bridge is the screen text the run captured, so a function whose screens were recorded converts with real guards — and one whose screens were not says so, per step, rather than producing a task that would act on any screen at all.
The draft also reports anything it dropped: a key a task cannot press, a field key it could not read, or a parameter no step fills. As with the wizard, it proposes no outputs.
By hand¶
The catalogue is server-side, so one person defines a task and everyone
else picks it off the menu. A task can also be written directly and posted to
/tasks/save:
{
"name": "Account balance enquiry",
"description": "Retrieves the current cleared balance for a customer account.",
"parameters": [
{
"name": "account_number",
"label": "Account number",
"required": true,
"maxLength": 8,
"pattern": "\\d{8}",
"example": "40218855"
}
],
"steps": [
{
"description": "Enter the account number",
"expect": [{ "row": 1, "column": 29, "text": "ACCOUNT ENQUIRY" }],
"inputs": [
{ "row": 5, "column": 21, "length": 8, "parameter": "account_number" }
],
"aidKey": "Enter"
},
{
"description": "Confirm the account was found",
"expect": [
{ "row": 22, "column": 2, "text": "INVALID ACCOUNT", "absent": true }
]
}
],
"outputs": [
{
"name": "cleared_balance",
"label": "Cleared balance",
"row": 8, "column": 21, "length": 14,
"pattern": "([\\d,]+\\.\\d{2})"
}
]
}
All rows and columns are 1-based, matching the CURSOR readout in the
OIA and the coordinates in a recording.
Parameters¶
| Field | Meaning |
|---|---|
name |
Machine identifier that steps refer to. Letters, digits, underscore. |
label |
What the form shows. Defaults to name. |
description |
Hint shown under the field. |
example |
Becomes the field's placeholder. |
default |
Pre-filled value. Not allowed on a sensitive parameter. |
required |
An empty value is refused before the run starts. |
maxLength |
Enforced in the form and again on the server. |
pattern |
RE2 expression. Anchored at both ends, so \d{8} means the whole value is eight digits, not "contains eight digits". |
sensitive |
Masked in the form and kept out of every result and log line. The host still receives it. |
Validation runs on the server on every run, not only in the browser. The form is a convenience, not the gate.
Steps¶
A step checks the screen, fills fields, then presses a key.
expectguards the step. Every entry must match before anything is typed. Setabsent: trueto require that text is not there — that is how a step refuses to read an error line as an answer.inputsset exactly one ofvalue(a literal, such as a menu selection) orparameter. An optional parameter left blank means leave the field alone, which on a 3270 is not the same as typing nothing.aidKeydefaults toEnter.PF1–PF24,PA1–PA3,Clear,AttnandSysReqare accepted. Leave it empty on a final step that only needs to confirm where the flow landed.
Guards are positional text, not a screen hash. A hash changes the moment the host paints a different date in the corner, and when it mismatches it can only report "a different screen". An anchor on the application's own label text survives cosmetic change and can say exactly what it wanted and what was there instead.
Outputs¶
An output names a region of the final screen.
| Field | Meaning |
|---|---|
name |
Machine identifier. |
label |
What the result card shows. |
row, column, length |
The region, 1-based, on a single line. |
pattern |
Optional RE2. With one capture group, the group is the value; without, the whole match is. |
optional |
Allows the value to be missing without failing the run. |
pattern is what turns Cleared balance: 1,240.55 CR into
1,240.55.
A region is a span on one line. An answer that wraps is two outputs — letting one run onto the next line would capture the label of whatever sits below it.
API¶
These endpoints use the browser session cookie.
| Method | Path | Purpose |
|---|---|---|
GET |
/tasks |
List the catalogue |
POST |
/tasks/save |
Add or replace a task, validated |
GET |
/tasks/draft |
Build a draft from the session's recording, or reopen a saved one with ?from= |
POST |
/tasks/preview |
Validate an unsaved task and report what its outputs would read |
POST |
/tasks/delete |
Remove a task by name |
POST |
/tasks/run |
Start a run in this session |
GET |
/tasks/status |
Progress, then the result |
POST |
/tasks/cancel |
Stop a run |
/tasks/preview answers 200 with ok: false and the reason when the task
is not valid yet: an incomplete task is the expected state of one being
authored, and the complaint belongs beside the field rather than in a failed
request. It reads the answer with the same code the runner uses, so a preview
that says a value cannot be read is a run that would fail.
/tasks/run returns 202 immediately and the run proceeds in the
background; poll /tasks/status for progress and the result. One run per
session — a task drives the single terminal that session owns, and two at
once would interleave keystrokes into the same screen buffer.
For bots and CI¶
The same capability is on the token-authenticated
REST API, which needs API_TOKEN set.
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/tasks |
The catalogue — this is also export |
POST |
/api/v1/tasks |
Add or replace a task — this is also import |
POST |
/api/v1/sessions/{id}/tasks/run |
Run a task in a session and return the result |
curl -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"Account balance enquiry","parameters":{"account_number":"40218855"}}' \
https://3270web.example/api/v1/sessions/$SID/tasks/run
{
"task": "Account balance enquiry",
"durationMs": 152,
"completed": true,
"steps": [{ "index": 1, "description": "Enter the account number", "status": "ok" }],
"outputs": [{ "name": "cleared_balance", "label": "Cleared balance",
"value": "1,240.55", "found": true }]
}
The API run is synchronous, unlike the browser's. The two callers want opposite things: a browser has to show progress and offer Cancel while a transaction takes its seconds, so it polls; a bot wants the answer in the response and would otherwise have to implement a poll loop to get it. Both are bounded by the same five-minute ceiling, and both register in the same per-session slot — so an API run and a browser run cannot overlap on one terminal.
A task that stopped early returns 200 with completed: false and the
failure detail, not an HTTP error. The request succeeded; the body says what
the host did. An HTTP status cannot express "step 3 saw the wrong screen", and
collapsing it into a 500 would discard the only useful part of the answer.
Export and import¶
GET /api/v1/tasks returns exactly the documents POST /api/v1/tasks
accepts, so moving a catalogue between deployments — or keeping it in version
control — needs no separate format:
# Export
curl -H "Authorization: Bearer $API_TOKEN" \
https://source.example/api/v1/tasks | jq '.tasks' > tasks.json
# Import, one task at a time
jq -c '.[]' tasks.json | while read -r t; do
curl -H "Authorization: Bearer $API_TOKEN" -H 'Content-Type: application/json' \
-d "$t" https://target.example/api/v1/tasks
done
Imported tasks go through the same validation as everything else, so a task edited by hand in version control cannot reach the runner malformed.
For moving a whole catalogue rather than one task, GET and
POST /api/v1/library do it in one call each way — and carry the connection
profiles with it, which is usually what a task catalogue needs at the far end
to be worth anything. That import reports what it did entry by entry, can be
asked what it would do first, and refuses a file it cannot store in full
rather than storing half of it. See
REST API, or
Admin → Session screen → Library for the same thing without curl.
Limits¶
- 200 tasks in the catalogue, 100 steps in a task.
- A run is abandoned after five minutes.
- Parameter values are capped at 160 characters and may not contain CR, LF or TAB, which the 3270 data stream would read as actions rather than text.
Sharing tasks¶
A saved task can be shipped to other installations inside an extension, alongside the skills and instructions that explain when to use it. See Skills and Extensions.