Ikanos — Schema — Steps¶
Steps enable multi-step orchestration — calling multiple consumed
operations in sequence and combining their results. Use steps anywhere
call: is allowed: on MCP tools, on REST operations, and on aggregate
flows.
Simple mode (single
call:) is preferred when one operation is enough. Orchestrated mode (steps:) is for multi-source composition and lookups.
Modes¶
| Mode | Looks like | Use when |
|---|---|---|
| Simple | call: + with: |
The tool delegates to a single consumed operation |
| Orchestrated | steps: + mappings: |
The tool combines multiple operations or joins data |
Exactly one mode is used per tool / operation / flow.
Anatomy of an orchestrated block¶
steps: # keyed map; key IS the step name
step1:
type: call
call: github.list-users
step2:
type: call
call: github.get-user
with:
username: "$.step1.users[0].login"
mappings:
- { target: output_field, value: "$.step2.userId" }
steps:is a keyed map keyed by step name. Iteration order is preserved and defines execution order.- Each step is referenced downstream by its map key.
mappings:glues the final step outputs to the exposed operation's output parameters.
Step types¶
type: call¶
Executes a consumed operation.
type: lookup¶
Searches through a previous step's output for a matching record. Useful for in-memory joins.
find-user-by-email:
type: lookup
index: list-all-users # name of an earlier `call` step
match: email # field in that step's output
lookupValue: "{{email_to_find}}"
outputParameters: ["fullName", "department"]
Variable references¶
Inside with: and mappings:, two reference styles are supported:
| Syntax | Resolves to |
|---|---|
"{{paramName}}" |
A Mustache template against tool input parameters and binds |
"$.stepName.fieldPath" |
The output of a previous step, addressed by JSONPath |
Examples:
with:
username: "{{github_username}}" # from tool input
organization: "$.fetch-user.organization" # from previous step
role: "ADMIN" # literal
Mappings¶
Mappings connect step outputs to the exposed operation's output parameters.
mappings:
- { target: database_name, value: "$.fetch-db.dbName" }
- { target: row_count, value: "$.query-db.totalRows" }
- { target: rows, value: "$.query-db.results" }
target:is the name of anoutputParameterdeclared on the exposed operation.value:is a JSONPath into any previous step's output.
Putting it together¶
get-user-by-email: # operation key under a REST resource
method: GET
path: "/users/by-email"
inputParameters:
email: { in: query, required: true }
steps:
list-all-users:
type: call
call: hr.list-employees
find-user:
type: lookup
index: list-all-users
match: email
lookupValue: shipyard-api.email
outputParameters: ["fullName", "department"]
mappings:
- { target: name, value: "$.find-user.fullName" }
- { target: department, value: "$.find-user.department" }
outputParameters:
- { name: name, type: string }
- { name: department, type: string }
When to refactor into an aggregate¶
If the same steps: block is used by more than one tool or operation,
move it into an aggregate flow and reference it via ref:. See
Aggregates for the full pattern.