Components
The Awee workflow engine. Portable, human- and LLM-readable automations wired with template expressions and run anywhere.
The Awee engine runs automation workflows. A workflow is a portable, declarative definition, an ordered list of steps where each step runs one component and every output flows to the steps that come after it through sintax template expressions. The same definition reads clearly to people and to language models, runs the same on any operating system, and is launched from a command-line app, a REST API, or the web app.
It is the engine behind Awee, the automation platform. The core runtime, control flow, and the file, HTTP, inference, and control components are built in. The App components connect a workflow straight to the Awee data platform.
Tip
New here? Start with Workflow anatomy and the guides beside it in the sidebar for a tour of the whole engine, the workflow format, templates, control flow, inference, execution plans, cost accounting, and modular composition. This page is the component reference, one page per step with its full options and outputs.
Awee pairs a static, inspectable execution plan with model-powered steps, per-run cost accounting, and multi-currency reporting, so an automation stays auditable even when a model is in the loop.
How it works
An ordered list of steps, readable by people and models alike.
Compiles the definition into a static plan with immutable, hierarchical step IDs. No I/O, no side effects.
Runs each step in order, and each step's result feeds every later step.
- Define a workflow. List the actions, pick a component for each, and wire outputs with sintax
{{ step.field }}expressions. - Plan. The engine compiles the definition into an
ExecutionPlanwith no I/O and no side effects. - Execute. Steps run in order, and conditions, loops, retries, and cache hits all resolve at runtime.
A first workflow
id: search-and-summarise
name: Search and Summarise
actions:
- name: page
component: http
vars:
url: "https://example.com/{{ topic | slug }}"
- name: summary
component: inference
vars:
provider: anthropic
model: claude-opus-4-20250514
prompt: "Summarise in three bullet points: {{ page.body }}"
cache:
for: 1h
- name: write
component: file:write
vars:
path: "./out/{{ topic | slug }}.md"
content: "{{ summary.content }}"Every field accepts {{ }} expressions. A prior step's output is referenced by its name, so {{ page.body }} reads the page step's body. Modifier chains such as {{ topic | slug | lower }} transform values inline, and {{ value | default:'x' }} supplies a fallback.
Control flow
Any step can carry an if condition, a retry policy, or a cache duration, and looping is the each component wrapping its body under actions. Conditions choose between a step and its else branch, loops run their child steps once per item, and a cache hit skips the step and injects the stored value. The control flow guide covers all of it.
Components
Each component links to its own page with its full options and outputs.
App
Tip
These components connect a workflow to the Awee data platform, turning schemas, tables, and records into steps.
Manage schemas, tables, fields, records, and files in the Awee app platform.
| Name | Description |
|---|---|
app:field | Retrieves the definition of a single field within a table |
app:field:create | Adds a new field to a table and applies the migration |
app:field:delete | Removes a field from a table and applies the migration |
app:field:list | Lists all fields defined within a table |
app:field:update | Changes the attributes a caller names on an existing field |
app:file:read | Retrieves file bytes without interpreting their format. |
app:file:save | Inserts a file record, uploads the blob, and stamps the resulting key back onto the record. Errors mid-flight leave the record in place with an empty Field, which is intentional so the row still shows up in audit and list views and operators can inspect the failure |
app:record | Retrieves a single record by ID from the given schema table |
app:record:bulk:delete | Soft-deletes a set of records in one write and returns the identifiers the write reached |
app:record:bulk:insert | Inserts a set of records into a schema table in one write and returns their identifiers |
app:record:bulk:update | Applies a patch across a set of records and returns the identifiers the write reached |
app:record:bulk:upsert | Writes a set of records into a schema table, addressing each by a business key rather than by an id. It exists so a workflow syncing anything stops carrying the "did this row already exist" branch. Answering that in the document costs a read, a compare and two conditional writes, and every one of those steps is a chance for the two branches to drift apart. The database already knows, through the unique index the match names, so the step asks it. |
app:record:delete | Soft-deletes a record by setting its deleted_at timestamp |
app:record:history | Retrieves the immutable audit log for a record, ordered oldest first |
app:record:insert | Inserts a new record into a schema table and returns the persisted record |
app:record:query | Queries records from a schema table using filters, sorting and pagination |
app:record:update | Applies a full replacement patch to an existing record and returns the updated record |
app:schema | Retrieves a single schema by ID for the given organization |
app:schema:create | Provisions a new database and applies the initial schema definition |
app:schema:create:many | Provisions multiple databases and applies their initial schema definitions |
app:schema:delete | Drops the database for the given schema ID |
app:schema:list | Lists all schemas belonging to an organization |
app:schema:update | Replaces the metadata of an existing schema |
app:table | Retrieves the definition of a single table within a schema |
app:table:create | Adds a new table to a schema and applies the migration |
app:table:delete | Removes a table from a schema and applies the migration |
app:table:list | Lists all tables defined within a schema |
app:table:update | Changes the parts a caller names on an existing table |
Data
Reshape, split, compare, and validate values without leaving the process.
| Name | Description |
|---|---|
data:csv:chunk | Splits a large CSV file into smaller chunk files of a fixed row count |
data:csv:merge | Merges columns from a secondary CSV file into a primary CSV file |
data:csv:shrink | Removes specified columns from a CSV file to reduce its width |
data:csv:unchunk | Combines multiple CSV chunk files back into a single output file |
data:document:extract | Walks a parsed document by segment pattern and emits keyed items. It reads the flat item list a document parse produces, keeps the items whose path matches the pattern, names the captured segments, and emits one output item per match. Repeated matches collapse into one item when group fields are configured, which is how plurals and arrays come back out of a document as a single entry. |
data:document:patch | Applies syntax-aware replacements without rebuilding the document. |
data:document:render | Writes a keyed list of items out as a document in one of the supported formats. Selection and patching are the pair for editing a document that already exists, while this one builds a document from data that never was one, which is what a workflow needs once it has assembled the entries itself. Every key and value is escaped for the format being written, so a value holding a separator, a quote, a backslash, or a line break survives a round trip. |
data:document:select | Reads syntax values without changing the source document. |
data:json:unchunk | Combines multiple JSON chunk files into a single array or map output file |
data:list:compare | Sorts two lists of items into buckets by comparing them key by key. Items pair up through the configured key paths, so the two lists may name the same thing differently. A pair whose compared values all agree is the same. A pair whose values disagree is classified against the base, which is git's three-way merge question and the only reason a base is accepted at all. The side that still equals the base did not move, so a pair lands in a_moved, b_moved or both_moved and a caller reads the merge policy straight off the bucket name instead of re-deriving it a step later. A pair with no base for its key is different, since nothing there says which side moved. Every bucket is emitted in key order and nothing is written anywhere. |
data:list:union | Coalesces two lists into one item per key, preferring the first list. Items pair up through the configured key paths, A's item is taken wherever a key appears in both, and B fills the keys A has nothing for. That is the link a precedence chain is built from, so a policy such as approved over published over base is a union of a union rather than a query that has to know the policy. Neither list may repeat a key, and nothing is written anywhere. |
data:shape:read | Reports the structure of a document a run is holding. |
data:validate | Checks that a content string is valid for a given format (csv, json, yaml) |
Each
Iterate over a list and run sub-steps for every item.
| Name | Description |
|---|---|
each | Loop over a collection of items or map entries, processing them one by one or in chunks. It is the block form of iteration, running the steps nested under it once per element, where a step's own each field runs that one step per element and collects what each produced. Both expand the collection through the same config and the same engine call, so the two cannot disagree about what an element is. |
Event
Emit events during workflow execution.
| Name | Description |
|---|---|
event:emit | Publishes an event to the configured topic so other pipeline steps or external systems can react |
Fail
Raise an explicit error to stop the workflow.
| Name | Description |
|---|---|
fail | Immediately fails the workflow step, either as a failure or, given a status and a code, as a refusal. |
Group
Group related steps under a single named step.
| Name | Description |
|---|---|
group | Is a control component that groups multiple components together It does not execute any logic itself, but serves as a container for other components |
HTTP
Make HTTP requests and crawl pages.
| Name | Description |
|---|---|
http:crawl | Searches the web for information via one of the integrated search providers |
http:request | Perform HTTP requests using the provided configuration |
LLM
Interact with AI language models.
| Name | Description |
|---|---|
llm:estimate | Estimates the token count and cost for a prompt without running the model |
llm:generate | Makes LLM inference requests using the configured provider and its model. Supports tools, LLM parameter settings and cost calculation with user currency conversion. Pass a template path to the prompt field, or a string prompt to render dynamic prompts with variables. |
llm:models | Lists all available models from the configured inference provider |
Machine
Drive the local machine, its shell, and the connected browser extension.
| Name | Description |
|---|---|
machine:agent:session:create | Runs one turn of a coding agent session against a working directory and returns the session it ran, the agent's final message, the tools it called and what the turn spent. The agent runs headless through its own CLI, which has to be installed on the machine the run happens on, and reports what it does as it does it on step.progress events, each carrying a type of session, message or tool on IO.Partial. A coding agent runs commands of its own, so the step is behind the same host permission as machine:shell:exec. |
machine:agent:session:list | Lists the sessions coding agents keep on the machine the run happens on, each with its tokens, cost, models and tool calls, the subagents it spawned included. A session whose agent recorded no cost is priced from the run's price table, and stays uncosted with an empty cost_source when a model it ran is not in that table. |
machine:agent:session:read | Reads one session a coding agent keeps on the machine the run happens on, with its messages, its turns, the subagents it spawned and what each of them spent. Tool inputs and outputs are left out, since they are bulky and routinely carry whatever secrets the agent saw. |
machine:extension:advance | Acts on the control that reaches a listing's next batch. The pipeline owns the repetition, so this takes one step towards the next page and returns. Whether there is a page after that is answered by observing again, which is the workflow document's turn rather than this component's. |
machine:extension:apply | Turns one model decision into a step and performs it on the live page, then reports what the next turn needs to know. A step the loop may not write, a ref the page does not hold and a step the page refused are all ordinary outcomes here rather than component failures. Each one comes back as Error, which is the text the next prompt shows the model, because a loop that stopped on them would throw away the one thing that lets the model correct itself. A step that hands the page to the person in front of it is the one turn this does not hold to the turn timeout. It waits on them for as long as the step allows, and the turn is given back to the session's budget, so a loop is never shortened by the waiting it asked for. |
machine:extension:author | Writes a browser workflow by driving a real browser. It observes the live page, asks a model for one step, applies that step in the session, and keeps the ones that worked, so the workflow it emits is a record of a run that actually happened rather than a guess at the site's markup. A step that fails is not discarded silently. Its error goes back into the next prompt, so the model corrects against what the page did rather than against what it assumed. What the loop may write covers the whole of what a page hands over. It reads prose and it reads listings as rows, and where the thing it was sent for is a file behind a form rather than something written on the page, it re-issues that form and keeps the bytes. A wall only a person can get through is not a failure either. The loop writes a step that hands the page to whoever is in front of it, says what they have to do, and waits, and neither the time they take nor the turn it took is charged to the session. |
machine:extension:emit | Assembles the steps an authoring session accepted into a workflow, pushes it into the extension's library when asked, and saves it as a file when the run set write. It is the end of the loop rather than a part of it, so it needs no bridge unless a sync was asked for. That is what lets a session run against a browser and still hand back its fragment when the browser has gone away. |
machine:extension:list | Reads a page's repeated items as rows. It is the read half of paging through a listing. The repetition itself is never here, because a fragment is a flat list of steps and a browser that owns the loop is a browser deciding when to stop. This reads the page it is pointed at and hands the rows back, and the workflow document decides whether there is another page. |
machine:extension:observe | Reads the live page through the connected browser extension and returns its interactive elements as refs a model can name. It is the eye of the authoring loop, and it is useful on its own when a workflow needs to branch on what a page is currently showing. |
machine:extension:prompt | Renders one turn of the authoring loop as a prompt. It exists so a workflow document can run the loop step by step and still ask the model the same question the one-shot machine:extension:author component asks. Nothing about it touches the browser, so a run can render a turn and read it without a bridge. |
machine:extension:recall | Resolves the fragment held for one site and intent, so a run nobody is watching starts from what the last run worked out. An agent-driven repair carries the fragment in and takes the rewrite back out, and that caller keeps storage. A scheduled run has no such caller, so without this it authors the page from nothing every time and throws the result away at the end. Nothing stored is a miss rather than an error. The first run for an intent has nothing to find by definition, and a step that failed there would refuse the one run whose whole job is to work the page out. |
machine:extension:remember | Lands what a run worked out back on the fragment store, and writes down how the replay before it went. It is the other half of machine:extension:recall and useless without it. Recalling alone reads what the last run knew and leaves this run's repair in the outputs, where the next run cannot find it, so a page that changed is authored from nothing again on every run and the counters that would say so stay blank. A run that replayed cleanly writes no body. There is nothing new to keep, and storing the body it was just given would file a second identical revision on every run. |
machine:extension:replay | Runs an already-authored fragment and says whether to trust what it returned. Authoring a fragment costs a model call per turn and a live browser session, so a workflow that authors on every run is paying that on every run for a page it already worked out. This is the fast path. It runs what was authored, holds the result against the contract that fragment promised, and reports a miss or a break rather than failing, because the caller's answer to both is the same and it is to author. A step error is the easy failure. The one that matters is the fragment that runs clean and returns nothing, which is what a site's redesign looks like from here. Every step reports ok, the run reports ok, and the rows are gone. The contract is the only thing standing between that and a workflow that quietly reads zero rows forever. |
machine:extension:run | Runs one library fragment in the connected browser extension and blocks until its result comes back. One invocation is one workflow: the fragment is referenced by id (never inlined), so the extension only ever executes what its library author fixed, parameterized by variables. Under the hood the run travels as a single-ref sequence, the reference-only shape the trust boundary calls for. |
machine:extension:sequence | Runs an ordered list of library fragments in the connected browser extension as one logical job (one tab/session, one cancelable id) and blocks until the per-fragment results come back. Use it when fragments must share a live browser session; when they are independent, prefer chained machine:extension:run steps so the pipeline owns the control flow between them. |
machine:extension:sync | Pushes the canonical fragment library to the connected browser extension and waits for its ack, so a pipeline seeds (or replaces) the fragment set that later machine:extension:run and machine:extension:sequence steps reference by id. The fragments are plain workflow JSON files in the extension's wire schema, one workflow per file. |
machine:shell:exec | Runs an arbitrary shell command and captures its stdout, stderr and exit code |
List, read, and send mail.
| Name | Description |
|---|---|
mail:list | Lists messages in a mailbox, newest first, through whichever connection answers the mail:list capability. |
mail:read | Fetches one message and returns its parsed headers and bodies, through whichever connection answers the mail:read capability. |
mail:send | Delivers one message through whichever connection answers the mail:send capability. |
Map
Transform a list by running sub-steps per item and collecting results.
| Name | Description |
|---|---|
map | Remaps and transforms values from a source object into a new output structure |
Print values to stdout for debugging.
| Name | Description |
|---|---|
print | Logs a labeled variable value to the debug output for inspection during development |
Search
Search the web for information.
| Name | Description |
|---|---|
search:web | Searches the web through the connection answering the search:web capability, so a workflow states the contract it needs and the connection decides which vendor serves it. |
Sleep
Pause workflow execution for a duration.
| Name | Description |
|---|---|
sleep | Is a control component that sleeps for a specified duration |
Storage
Read and write files on the local machine, Google Drive, and OneDrive.
| Name | Description |
|---|---|
storage:google:drive:list | Lists Google Drive files visible to the app's drive.file grant, using a connection resolved from the connections store. |
storage:google:drive:read | Downloads one Google Drive file's metadata and content, using a connection resolved from the connections store. |
storage:google:drive:write | Writes content into Google Drive under the app's drive.file grant, creating a new file or replacing an existing one, using a connection resolved from the connections store. |
storage:local:dir:read | Read a directory with filters |
storage:local:dir:write | Create or delete a directory |
storage:local:file:copy | Copies a file from source to destination, preserving file permissions |
storage:local:file:find | |
storage:local:file:read | Reads the full contents of a file and returns it as both a string and raw bytes |
storage:local:file:write | Writes or appends content to a file, optionally deleting it first |
storage:local:synced:list | Detects locally synced Google Drive for Desktop and OneDrive folders and returns their local root paths, so workflows read and write provider files with the plain fs components and zero API auth. |
storage:microsoft:onedrive:list | Lists the children of a OneDrive or SharePoint folder over Microsoft Graph, using a connection resolved from the connections store. |
storage:microsoft:onedrive:read | Downloads one OneDrive or SharePoint file's metadata and content over Microsoft Graph, using a connection resolved from the connections store. |
storage:microsoft:onedrive:write | Writes content into a OneDrive or SharePoint drive over Microsoft Graph, creating or replacing the target file, using a connection resolved from the connections store. |
Template
Render a text template.
| Name | Description |
|---|---|
template | Renders a template |
Var
Set or pass through a variable value.
| Name | Description |
|---|---|
var | Sets or appends a variable in the workflow context for use in subsequent steps |