Materialization Plans
Materialization turns a capability graph into runnable artifacts. Webcmd uses a two-step flow: prepare a packet from graph context, then apply an agent-authored plan that matches the packet schema.
Workflow materialization
webcmd workflow <app-id> --task "Collect top stories"
# writes .webcmd/graphs/<app-id>/workflow.packet.json
webcmd workflow <app-id> --plan .webcmd/graphs/<app-id>/workflow.plan.json
# writes .webcmd/exports/workflows/<domain>/<workflow-id>.mjs
Workflow plan schema:
{
"workflowId": "top-stories",
"uses": [
{ "capability": "hacker_news.list_top_stories", "with": { "limit": "$limit" } }
],
"params": {
"limit": {
"type": "number",
"required": false,
"description": "Maximum number of stories to return"
}
},
"script": "complete executable ESM source"
}
Constraints:
| Field | Rule |
|---|---|
workflowId | Single path segment; no /, \, ., or ... |
uses | At least one known graph capability. |
params | Optional record of typed workflow args: string, number, boolean, json. |
script | Complete .mjs workflow source. |
The script must export workflow = { version: 1, id, task, params, output? } and run(input, options). It should import only createWorkflowRuntime and parseWorkflowArgs from webcmd/runtime, use public runtime methods, honor auth summary, close the runtime, and avoid importing graph/session sidecar files at runtime.
CLI materialization
webcmd cli <app-id> --task "Create a jobs CLI"
# writes .webcmd/graphs/<app-id>/cli.packet.json
webcmd cli <app-id> --plan .webcmd/graphs/<app-id>/cli.plan.json
webcmd cli <app-id> --plan .webcmd/graphs/<app-id>/cli.plan.json --install-skill
webcmd cli <app-id> --plan .webcmd/graphs/<app-id>/cli.plan.json --export skill --force
CLI plans are discriminated by mode.
Create plan
{
"mode": "create",
"commands": [
{
"name": "search",
"description": "Search jobs by keyword",
"uses": ["linkedin.search_jobs"],
"localCode": ["src/index.mjs"],
"smokeTest": {
"args": ["search", "--help"],
"expect": "Search jobs"
}
}
],
"files": {
"package.json": "{ ... }",
"src/index.mjs": "..."
}
}
files must not be empty. File paths must stay inside the generated package, target files rather than the package root, avoid absolute paths, avoid .., and pass package path validation.
Update plan
{
"mode": "update",
"intent": "add-command",
"commands": [
{
"name": "saved",
"description": "List saved jobs",
"uses": ["linkedin.list_saved_jobs"],
"localCode": ["src/index.mjs"],
"smokeTest": {
"args": ["saved", "--help"],
"expect": "saved"
}
}
],
"edits": [
{
"path": "src/index.mjs",
"operation": "replace",
"content": "..."
}
],
"remove": []
}
intent must be add-command, modify-command, remove-command, or refresh-docs. edits must contain at least one write/replace operation. If the plan edits SKILL.md or changes command metadata, commands is required.
CLI command contracts
| Field | Meaning |
|---|---|
name | Generated command name. |
description | Human/agent readable command summary. |
uses | Capability ids used by this command; every id must exist in the graph. |
localCode | Generated package files that implement the command. |
smokeTest.args | Safe validation args; must include --help, --dry-run, or --validate. |
smokeTest.expect | Output text expected from the smoke test. |
Auth-aware workflow implementation
Materialization packets include authSummary. Use it before choosing the runtime pattern:
| Capability auth | Workflow pattern |
|---|---|
| Public-only | createWorkflowRuntime(options). |
browser-cookie or browser-request | createWorkflowRuntime({ ...options, auth: true }); use browser context/http as appropriate. |
page-fetch | Initialize with auth when profile is required, navigate to an allowed app origin, then runtime.pageFetch({ ..., allowedOrigins }). |
intercept | Use runtime.waitForResponse(matcher, action) with a narrow graph-approved matcher and minimal UI trigger. |
manual or unsupported | Do not invent hidden HTTP or credential extraction; report the unsupported path unless UI replay is enough. |
Verification
webcmd verify .webcmd/exports/workflows/<domain>/<workflow-id>.mjs
webcmd verify .webcmd/exports/clis/<domain>
Workflow verification loads the script and runs it with an injected fake runtime. Generated CLI verification validates package structure and metadata. Neither path uses real credentials.