Your First Flow
Build a three-step Flow where each Step needs an output from the one before it. See how the planner walks backward from a single goal to assemble the execution plan automatically.
What You’ll Build
A simple order processing Flow with three Steps:
- lookup-customer: fetch customer data by ID
- validate-payment: validate customer has credit available
- send-confirmation: send an order confirmation email
These Steps form a dependency chain: send-confirmation needs validate-payment to complete, which needs customer data from lookup-customer.
Step 1: Register the lookup-customer Step
This is a resolver Step that provides customer data:
curl -X POST http://localhost:8080/engine/step \
-H "Content-Type: application/json" \
-d '{
"id": "lookup-customer",
"name": "Lookup Customer",
"type": "sync",
"http": {
"method": "GET",
"endpoint": "https://api.example.com/customers/{customer_id}",
"timeout": 5000
},
"attributes": {
"customer_id": {"role": "required", "type": "string"},
"customer": {"role": "output", "type": "object"}
}
}'
What this Step declares:
- It needs a
customer_id(required input) - It produces a
customerobject (output) - It’s an HTTP GET request that needs the customer_id in the URL
Step 2: Register the validate-payment Step
This Step takes customer data and validates it:
curl -X POST http://localhost:8080/engine/step \
-H "Content-Type: application/json" \
-d '{
"id": "validate-payment",
"name": "Validate Payment",
"type": "sync",
"http": {
"method": "POST",
"endpoint": "https://api.example.com/validate-payment",
"timeout": 5000
},
"attributes": {
"customer": {"role": "required", "type": "object"},
"order_amount": {"role": "required", "type": "number"},
"valid": {"role": "output", "type": "boolean"}
}
}'
Key point: This Step requires customer, which is the output of lookup-customer. Argyll will automatically wire them together.
Step 3: Register the send-confirmation Step
This Step sends a confirmation to the customer:
curl -X POST http://localhost:8080/engine/step \
-H "Content-Type: application/json" \
-d '{
"id": "send-confirmation",
"name": "Send Confirmation",
"type": "sync",
"http": {
"method": "POST",
"endpoint": "https://api.example.com/send-email",
"timeout": 5000
},
"attributes": {
"customer": {"role": "required", "type": "object"},
"valid": {"role": "required", "type": "boolean"},
"confirmation_sent": {"role": "output", "type": "boolean"}
}
}'
Step 4: Start the Flow
Now start a Flow with send-confirmation as the Goal:
curl -X POST http://localhost:8080/engine/flow \
-H "Content-Type: application/json" \
-d '{
"id": "order-123",
"goals": ["send-confirmation"],
"init": {
"customer_id": ["cust-456"],
"order_amount": [99.99]
}
}'
What Argyll Does
Planning Phase
- Goal is send-confirmation. What does it need?
- It needs
customerandvalid - Argyll looks for a Step that produces
customer. Found: lookup-customer - Argyll looks for a Step that produces
valid. Found: validate-payment - validate-payment needs
customer(from lookup-customer) andorder_amount(from init) - lookup-customer needs
customer_id(from init) - All dependencies satisfied. Plan is complete.
Execution Phase
- Run lookup-customer with customer_id=“cust-456”. Output: customer={…}
- Run validate-payment with customer={…} and order_amount=99.99. Output: valid=true
- Run send-confirmation with customer={…} and valid=true. Output: confirmation_sent=true
- All Goals satisfied. Flow completes.
Inspect the Result
curl http://localhost:8080/engine/flow/order-123
The response shows the complete Flow state:
{
"id": "order-123",
"status": "completed",
"attributes": {
"customer_id": [{ "value": "cust-456" }],
"order_amount": [{ "value": 99.99 }],
"customer": [
{
"value": { "id": "cust-456", "name": "Alice" },
"step": "lookup-customer"
}
],
"valid": [{ "value": true, "step": "validate-payment" }],
"confirmation_sent": [{ "value": true, "step": "send-confirmation" }]
},
"executions": {
"lookup-customer": { "status": "completed" },
"validate-payment": { "status": "completed" },
"send-confirmation": { "status": "completed" }
}
}
Each Attribute is an array of value records since multiple upstream Steps can produce the same Attribute. The step field shows which Step produced each value (omitted for init values).
Key Insights
No explicit wiring: You didn’t write code to “pass customer from Step A to Step B”. Argyll matched the output name to the input name automatically.
Dependency discovery: You didn’t write “execute lookup-customer, then validate-payment, then send-confirmation”. Argyll walked backward from the Goal and figured out the order.
Minimal work: If you started a Flow with a different Goal (e.g., just “validate-payment”), it would still run lookup-customer (because validate-payment needs it) but skip send-confirmation.
Next Steps
- Read Steps to understand all Step types (sync, async, script, sub-flows)
- Read Flows to understand Flow lifecycle and terminal states
- Read Attributes & Roles to understand input/output/const/meta attributes and collection policies
- Explore HTTP Steps to learn about request/response handling