Guides

For Agents

Designing requests people answer in seconds.

What a good request is

A Taskriz request is a small native screen your Agent sends to a person. The best ones have one clear task, show only what’s needed to do it, and take a tap or two to answer — on a phone, a laptop, wherever the person is. If it would be a form you’d skim past, make it shorter.

Principles

Taskriz requests follow world-leading human interface guidelines, so they feel familiar at first glance.

The building blocks

An interface is built from these (and a few more — get_ui_guide has them all). You read what the person chose from the control when they tap a button.

Building blockForRead
SegmentedControlMorphA choice of 2–5 (Window · Middle · Aisle)selected
PopUpButtonMorphA choice from more optionsselected
SwitchMorphYes / no, on / offon
StepperMorphA small number in a range (quantities)value
SliderMorphA value in a rangevalue
DatePickerMorphA date, a time, or bothvalue (ISO 8601)
TextFieldMorphOne line of text (with keyboards for email, numbers, phone…)value
TextViewMorphSeveral lines of textvalue
PhotoPickerMorphA photo — chosen or taken on the spotfiles
DocumentPickerMorphA document (PDF, Word…)files
CollectionViewMorphA grid to choose from — pictures, cards (tapped cells show a checkmark)selected (0-based)
ListMorphA form or table — group related fields (style: #insetGrouped)—
LabelMorphText: what they need to know (text styles: #headline, #footnote…)—
ImageMorphA picture or symbol (always give alt:)—
ButtonMorphThe action — one primary (filled), others style: #plain—

Worked examples

These are the requests on the Taskriz home page — real, and tested.

Approve an invoice

A decision with an optional note: the facts in a grouped list, the main action filled, the alternative plain.

| note |
note := TextFieldMorph new label: 'Note'; placeholder: 'Optional'.
ScreenMorph new title: 'Invoice #4567';
  addMorph: (LabelMorph new text: 'Acme Ltd sent invoice #4567 for October hosting.');
  addMorph: (ListMorph new style: #insetGrouped; header: 'Details';
    addMorph: (TextFieldMorph new label: 'Amount'; value: '$1,240.00');
    addMorph: (TextFieldMorph new label: 'Due'; value: 'Friday, Oct 16');
    addMorph: note; yourself);
  addMorph: (ButtonMorph new label: 'Approve'; onClick: [Taskriz current reply: #{ #decision -> 'approve'. #note -> note value }]);
  addMorph: (ButtonMorph new label: 'Query This Invoice'; style: #plain; onClick: [Taskriz current reply: #{ #decision -> 'query'. #note -> note value }]);
  yourself

Order supplies

Quantities with steppers, an option with a switch — and a running total the person sees change as they adjust.

| paper coffee pens express cost |
paper := StepperMorph new label: 'Paper · $45'; min: 0 max: 10 value: 2.
coffee := StepperMorph new label: 'Coffee · $38'; min: 0 max: 10 value: 3.
pens := StepperMorph new label: 'Pens · $9'; min: 0 max: 20 value: 1.
express := SwitchMorph new label: 'Express delivery · $15'.
cost := [(paper value * 45) + (coffee value * 38) + (pens value * 9) + (express on ifTrue: [15] ifFalse: [0])].
ScreenMorph new title: 'Office Supplies';
  addMorph: (LabelMorph new text: 'This week’s order for the office. Change the amounts if you need to.');
  addMorph: (ListMorph new style: #insetGrouped; header: 'Items'; addMorph: paper; addMorph: coffee; addMorph: pens; yourself);
  addMorph: (ListMorph new style: #insetGrouped; addMorph: express; yourself);
  addMorph: (LabelMorph new textStyle: #headline; textBlock: ['Total: $', cost value printString]);
  addMorph: (ButtonMorph new label: 'Place Order'; onClick: [Taskriz current reply: #{ #paper -> paper value. #coffee -> coffee value. #pens -> pens value. #expressDelivery -> express on. #total -> ('$', cost value printString) }]);
  addMorph: (ButtonMorph new label: 'Skip This Week'; style: #plain; onClick: [Taskriz current reply: #{ #decision -> 'skip' }]);
  yourself

Get a receipt photo

Ask for a file with a picker — never a link or a file path. A second button covers “I don’t have it”.

| photo |
photo := PhotoPickerMorph new label: 'Receipt'.
ScreenMorph new title: 'Receipt Needed';
  addMorph: (LabelMorph new text: 'Your card was charged $86.50 at Bistro Moncur on Tuesday. Add a photo of the receipt so the expense can be filed.');
  addMorph: (ListMorph new style: #insetGrouped; addMorph: photo; yourself);
  addMorph: (ButtonMorph new label: 'Send'; onClick: [photo files isEmpty ifFalse: [Taskriz current reply: #{ #receipt -> photo files }]]);
  addMorph: (ButtonMorph new label: 'I Don’t Have It'; style: #plain; onClick: [Taskriz current reply: #{ #receipt -> 'none' }]);
  yourself

Book a time

A date picker limited to the days that work, and the times as a segmented choice.

| day time |
day := DatePickerMorph new label: 'Day'; mode: #date; value: '2026-10-20'; min: '2026-10-19'; max: '2026-10-23'.
time := SegmentedControlMorph new label: 'Time'; segments: #('9:30' '11:00' '14:00'); selected: '11:00'.
ScreenMorph new title: 'Find a Time';
  addMorph: (LabelMorph new text: 'A 30-minute call next week. Which day and time suit you?');
  addMorph: (ListMorph new style: #insetGrouped; addMorph: day; addMorph: time; yourself);
  addMorph: (ButtonMorph new label: 'Book'; onClick: [Taskriz current reply: #{ #day -> day value. #time -> time selected }]);
  yourself

Choose an album

A grid of pictures to pick from; the person can change their mind before tapping Choose.

| albums grid cover |
albums := #('Neon Static' 'Slow Orbit' 'Paper Lanterns' 'Low Tide').
cover := [:title :artist :file | StackViewMorph new axis: #vertical;
  addMorph: (ImageMorph new src: '/renderers/web/task/covers/', file, '.svg'; alt: title);
  addMorph: (LabelMorph new text: title; textStyle: #subheadline);
  addMorph: (LabelMorph new text: artist; textStyle: #caption1); yourself].
grid := CollectionViewMorph new columns: 2;
  addMorph: (cover value: 'Neon Static' value: 'The Glass Arcade' value: 'neon-static');
  addMorph: (cover value: 'Slow Orbit' value: 'Mira Vale' value: 'slow-orbit');
  addMorph: (cover value: 'Paper Lanterns' value: 'Kites & Co.' value: 'paper-lanterns');
  addMorph: (cover value: 'Low Tide' value: 'The Lowlands' value: 'low-tide'); yourself.
ScreenMorph new title: 'Friday’s Album';
  addMorph: (LabelMorph new text: 'Pick the album for Friday’s office playlist.');
  addMorph: grid;
  addMorph: (ButtonMorph new label: 'Choose'; onClick: [grid selected isNil ifFalse: [Taskriz current reply: #{ #album -> (albums at: grid selected + 1) }]]);
  yourself

Designing the answer

A button sends the answer with Taskriz current reply: #{ … }. Shape it as the data your Agent wants to read: it arrives as JSON in the event’s reply — #{ #decision -> 'approve'. #note -> note value } becomes {"decision": "approve", "note": "…"}. Use clear keys, one answer per button, and put a picker’s files straight in (each arrives as {id, name, type, size}).

Testing

Before sending, run the interface with check_ui: it runs in the real Taskriz runtime and returns the error, or a text preview of what the person will see. The plugins check every request before sending it; on the API, test your interfaces with check_ui before you ship them.

Threads and follow-ups

Requests that share a correlationId are one thread for the person: ask a follow-up on the same thread and they see the conversation together. A request can allow one answer (the default) or several (replies: multiple). Sent the wrong thing? Recall it.

Respecting people

The request catalog

Give people actions they can start themselves — “Report a problem”, “Request a statement”. Keep labels short and specific (up to 60 characters), add a one-line description, and answer the initiate event with a request that collects what you need. How many actions an Agent can offer follows your plan: Free plans include 2 actions per Agent, Builder 10 and Business 50 (see Pricing). Developers shows how to set them.

Next: Developers — the API, the plugins and the MCP tools.