docs: plan workflow console and interrupt contracts
This commit is contained in:
@@ -22,6 +22,37 @@ The durable product path is now `wf-rpc-server` plus neutral `wf_config` /
|
||||
`wf_server` composition. The old `wf-mcp` script remains a legacy/special-purpose
|
||||
MCP entrypoint and compatibility surface.
|
||||
|
||||
## Active Initiative: Workflow Console And Defense Demo
|
||||
|
||||
The next product-facing push is a local-first web console and defense demo that
|
||||
shows the lifecycle without forcing viewers to read raw JSON. It connects to a
|
||||
loopback `wf-rpc-server` through JSON-RPC, displays lifecycle records and traces,
|
||||
and runs a prepared `lda.chat` report workflow with a typed human approval
|
||||
interrupt.
|
||||
|
||||
Design contracts:
|
||||
|
||||
- [`workflow console, agent demo, and defense presentation`](superpowers/specs/2026-07-01-workflow-console-agent-demo.md)
|
||||
- [`self-describing interrupt contracts`](superpowers/specs/2026-07-01-self-describing-interrupt-contracts.md)
|
||||
|
||||
Implementation order:
|
||||
|
||||
1. Add self-describing interrupt request/resume schemas to the core run/inspect
|
||||
contract.
|
||||
2. Add a deterministic `examples/lda_report_workflow/` case study with local
|
||||
document, report, and issue-board sources.
|
||||
3. Add a top-level `web/` Astro/Effect app with loopback JSON-RPC connection and
|
||||
method registry.
|
||||
4. Add console read/inspect views for sources, drafts, artifacts, deployments,
|
||||
runs, traces, and raw RPC drawers.
|
||||
5. Add lifecycle autoplay, typed approval, issue-board output, and replay.
|
||||
6. Add a constrained demo agent that invokes one prepared recipe macro.
|
||||
7. Add presentation and appendix routes for the 15-minute defense.
|
||||
|
||||
Boundaries: this is not a production admin panel, generic visual workflow
|
||||
editor, scheduler, external Google Drive/mail integration, or benchmark evidence
|
||||
for free-form autonomous planning.
|
||||
|
||||
## Priority 1: Product Smoke And Status UX
|
||||
|
||||
The platform is usable enough to test as a product. Next work should focus on
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,308 @@
|
||||
# Self-Describing Interrupt Contracts
|
||||
|
||||
Date: 2026-07-01
|
||||
|
||||
Status: Approved direction. Needs an executable implementation plan before code
|
||||
changes.
|
||||
|
||||
Related:
|
||||
|
||||
- [Current roadmap](../../current_roadmap.md)
|
||||
- [Persisted run/resume contract](2026-06-03-persisted-run-resume-contract.md)
|
||||
- [Workflow console, agent demo, and defense presentation](2026-07-01-workflow-console-agent-demo.md)
|
||||
- [Thesis system design](../../thesis/system-design-implementation.md)
|
||||
|
||||
## Purpose
|
||||
|
||||
Make human-in-the-loop workflow pauses self-describing. A client inspecting an
|
||||
interrupted run should know:
|
||||
|
||||
- what kind of interrupt occurred;
|
||||
- what payload was sent to the user;
|
||||
- which resume outcomes are valid;
|
||||
- what JSON shape a resume payload must have;
|
||||
- how to validate the response before sending `resume_run`.
|
||||
|
||||
This is required for the Workflow Console and useful for CLI, JSON-RPC, MCP, and
|
||||
agent clients. It prevents every client from needing workflow-specific code just
|
||||
to render and answer an approval step.
|
||||
|
||||
## Current Gap
|
||||
|
||||
The current core interrupt model has useful mechanics but not a complete public
|
||||
contract.
|
||||
|
||||
- `InterruptNode` stores `kind`, request bindings, resume bindings, and resume
|
||||
outcomes.
|
||||
- Runtime builds an `InterruptRequest` with id, frame id, node id, kind,
|
||||
payload, route, and resumability.
|
||||
- `workflow.runs.inspect` serializes the current runtime interrupt request.
|
||||
- Resume validates the selected outcome against `InterruptNode.outcomes` and
|
||||
applies resume bindings.
|
||||
|
||||
What is missing is a machine-readable schema for the request payload and resume
|
||||
payload. A client can see data, but it cannot know whether the response should
|
||||
be `{ "approved": true }`, `{ "selected_issue_ids": [...] }`, or something else
|
||||
without reading workflow code or challenge-specific docs.
|
||||
|
||||
This is close to the LangGraph-style `interrupt(value)` and `Command(resume=...)`
|
||||
pattern: flexible and simple, but the response contract is mostly app
|
||||
convention. `wf` should keep the flexibility while making the contract explicit.
|
||||
|
||||
## Design Summary
|
||||
|
||||
Add JSON Schema contracts to interrupt nodes and carry them through persisted run
|
||||
inspection and resume validation.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Runtime
|
||||
participant Store
|
||||
participant Client
|
||||
|
||||
Runtime->>Runtime: Build request payload from interrupt.request bindings
|
||||
Runtime->>Runtime: Validate payload against request_schema
|
||||
Runtime->>Store: Persist interrupted run checkpoint
|
||||
Client->>Store: inspect_run(run_id)
|
||||
Store-->>Client: payload, outcomes, request_schema, resume_schema
|
||||
Client->>Client: Render form from resume_schema
|
||||
Client->>Store: resume_run(run_id, payload, outcome)
|
||||
Store->>Runtime: Validate resume payload against resume_schema
|
||||
Runtime->>Runtime: Apply interrupt.resume bindings
|
||||
```
|
||||
|
||||
## Core Model
|
||||
|
||||
Extend `InterruptNode` with two optional schema fields:
|
||||
|
||||
```python
|
||||
class InterruptNode(BaseModel):
|
||||
id: str
|
||||
type: Literal["interrupt"]
|
||||
kind: str
|
||||
request: list[InputBinding] = Field(default_factory=list)
|
||||
resume: list[OutputBinding] = Field(default_factory=list)
|
||||
outcomes: list[str] = Field(default_factory=lambda: ["submitted"])
|
||||
request_schema: JsonSchemaObject = Field(default_factory=_object_schema)
|
||||
resume_schema: JsonSchemaObject = Field(default_factory=_object_schema)
|
||||
```
|
||||
|
||||
The default schema is a permissive object schema:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
```
|
||||
|
||||
This preserves existing persisted workflow documents and current examples. New
|
||||
authoring helpers should emit explicit schemas whenever they can.
|
||||
|
||||
## Runtime Request Contract
|
||||
|
||||
When an interrupt node executes:
|
||||
|
||||
1. Build the request payload using existing `request` bindings.
|
||||
2. Validate the built payload against `request_schema`.
|
||||
3. If validation fails, fail the run with a structured execution error. This is
|
||||
a workflow contract bug, not a human pause.
|
||||
4. Persist the interrupted run with an `InterruptRequest` that includes:
|
||||
- interrupt id;
|
||||
- frame id;
|
||||
- node id;
|
||||
- kind;
|
||||
- payload;
|
||||
- resumable flag;
|
||||
- child interrupt route when present;
|
||||
- outcomes;
|
||||
- request schema;
|
||||
- resume schema;
|
||||
- `typed=true` when the schema was explicitly declared.
|
||||
|
||||
The runtime should not infer request schemas from payload values. Inference
|
||||
would make the public contract depend on one execution instance rather than the
|
||||
workflow definition.
|
||||
|
||||
## Resume Contract
|
||||
|
||||
Before mutating run state, `resume_run` validates:
|
||||
|
||||
1. the run is currently interrupted;
|
||||
2. the selected resume outcome is declared by the interrupt node;
|
||||
3. the resume payload satisfies the interrupt node's `resume_schema`.
|
||||
|
||||
Only after those checks pass should the runtime apply `resume` bindings and
|
||||
advance the graph. Invalid resume payloads must not consume the interruption or
|
||||
write partial state changes.
|
||||
|
||||
Resume validation should use the same JSON Schema validation helper used by
|
||||
workflow validation where possible. Do not hand-roll schema validation.
|
||||
|
||||
## Public Inspect Shape
|
||||
|
||||
`workflow.runs.inspect` should expose the interrupt contract directly:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "interrupted",
|
||||
"interrupt": {
|
||||
"id": "interrupt:review",
|
||||
"frame_id": "frame_1",
|
||||
"node_id": "review",
|
||||
"kind": "issue_review",
|
||||
"payload": {
|
||||
"report_markdown": "# lda.chat Thesis And Project Readiness Report",
|
||||
"proposed_issues": []
|
||||
},
|
||||
"outcomes": ["submitted", "cancelled"],
|
||||
"request_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"report_markdown": {"type": "string"},
|
||||
"proposed_issues": {"type": "array"}
|
||||
},
|
||||
"required": ["report_markdown", "proposed_issues"]
|
||||
},
|
||||
"resume_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"approved": {"type": "boolean"},
|
||||
"selected_issue_ids": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"comment": {"type": "string"}
|
||||
},
|
||||
"required": ["approved", "selected_issue_ids"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"typed": true,
|
||||
"resumable": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The schema snapshot is part of the interrupted run's public contract. A client
|
||||
should not need to reload the mutable artifact or inspect Python source code to
|
||||
answer the interrupt.
|
||||
|
||||
## Authoring Contract
|
||||
|
||||
Raw workflow plans may specify `request_schema` and `resume_schema` directly on
|
||||
interrupt nodes.
|
||||
|
||||
Authoring helpers may provide convenience wrappers:
|
||||
|
||||
- direct JSON Schema dictionaries;
|
||||
- Pydantic models converted through `model_json_schema()`;
|
||||
- a small built-in helper for common approval forms.
|
||||
|
||||
The stored workflow should still contain ordinary JSON Schema dictionaries.
|
||||
Python type objects must not leak into persisted artifacts.
|
||||
|
||||
The first planned demo uses:
|
||||
|
||||
- `kind="issue_review"`;
|
||||
- a request schema containing rendered report markdown and proposed issues;
|
||||
- a resume schema containing approval, selected issue ids, and optional comment;
|
||||
- outcomes `submitted` and `cancelled`.
|
||||
|
||||
## Validation Contract
|
||||
|
||||
Workflow validation should catch static interrupt contract errors:
|
||||
|
||||
- `request_schema` and `resume_schema` must be valid JSON Schema documents;
|
||||
- schemas must describe JSON objects for V1;
|
||||
- request binding targets must be valid local payload paths;
|
||||
- resume binding sources must be valid local payload paths;
|
||||
- resume binding destinations must write to declared state fields;
|
||||
- every declared resume outcome that is routed must be known by the node.
|
||||
|
||||
V1 does not need full static proof that every request binding output satisfies
|
||||
`request_schema`. Runtime validation still protects execution. Static validation
|
||||
can become stricter later if it remains useful and maintainable.
|
||||
|
||||
## CLI And RPC Behavior
|
||||
|
||||
CLI and RPC should surface schema failures as ordinary structured product
|
||||
errors, not Python tracebacks.
|
||||
|
||||
Recommended behavior:
|
||||
|
||||
- `wf run inspect <run_id>` includes the interrupt schemas in JSON output.
|
||||
- Compact/text output summarizes `kind`, valid outcomes, and required resume
|
||||
fields.
|
||||
- `wf run resume <run_id> --input ...` validates before mutation and reports
|
||||
missing/invalid resume fields.
|
||||
- `wf explain` gains cards for interrupt request-schema and resume-schema
|
||||
validation failures if new diagnostic codes are added.
|
||||
|
||||
## Compatibility
|
||||
|
||||
Existing workflows without explicit schemas remain valid.
|
||||
|
||||
- Missing `request_schema` or `resume_schema` is treated as a permissive object
|
||||
schema.
|
||||
- Public inspect can include `typed=false` for legacy interrupts.
|
||||
- New authoring helpers and examples should emit explicit schemas.
|
||||
- No migration is required for stored artifacts.
|
||||
|
||||
Compatibility here is justified because raw workflow plans and saved artifacts
|
||||
are a documented external/persisted contract.
|
||||
|
||||
## Workflow Console Usage
|
||||
|
||||
The Workflow Console uses this contract to render generic human approval forms:
|
||||
|
||||
1. inspect the interrupted run;
|
||||
2. read `interrupt.kind` and `interrupt.resume_schema`;
|
||||
3. choose a kind-specific renderer when available;
|
||||
4. fall back to a generic JSON Schema form;
|
||||
5. validate locally for user feedback;
|
||||
6. send the resume payload through JSON-RPC;
|
||||
7. display server-side validation errors if the schema check still fails.
|
||||
|
||||
The console may provide a custom renderer for `issue_review`, but the custom
|
||||
renderer must still emit a payload accepted by `resume_schema`.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- New interrupt execution semantics.
|
||||
- Multi-user approval workflow.
|
||||
- Authentication, authorization, or audit identity.
|
||||
- Scheduling or event-triggered resumes.
|
||||
- A full JSON Schema UI standard.
|
||||
- Semantic compatibility analysis between schema revisions.
|
||||
- LangGraph API compatibility.
|
||||
|
||||
## Implementation Slices
|
||||
|
||||
1. Extend core models and persistence-safe serialization.
|
||||
2. Validate request and resume schemas using the existing schema validation
|
||||
library path.
|
||||
3. Carry interrupt schemas and outcomes into `InterruptRequest` and
|
||||
`workflow.runs.inspect`.
|
||||
4. Validate resume payloads before state mutation.
|
||||
5. Add authoring/builder helpers and schema discovery output.
|
||||
6. Update CLI docs, skills, and examples.
|
||||
7. Add the `issue_review` interrupt to the prepared `lda.chat` report workflow.
|
||||
|
||||
## Test Plan
|
||||
|
||||
- Core model accepts explicit schemas and defaults legacy nodes.
|
||||
- Invalid interrupt schemas are rejected by workflow validation.
|
||||
- Runtime validates a request payload before persisting interruption.
|
||||
- Resume rejects invalid payloads without mutating run state.
|
||||
- Resume rejects unknown outcomes before mutating run state.
|
||||
- `workflow.runs.inspect` includes schemas, outcomes, typed flag, and payload.
|
||||
- JSON-RPC and CLI resume return structured errors for invalid payloads.
|
||||
- Draft/raw-plan compilation preserves interrupt schemas.
|
||||
- Builder/Pydantic convenience emits plain JSON Schema in saved workflows.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The contract is complete when an external client can inspect an interrupted run,
|
||||
render a correct form, submit a valid resume payload, and explain invalid
|
||||
responses without reading workflow source code or hard-coding that workflow's
|
||||
interrupt shape.
|
||||
@@ -0,0 +1,428 @@
|
||||
# Workflow Console, Agent Demo, And Defense Presentation
|
||||
|
||||
Date: 2026-07-01
|
||||
|
||||
Status: Approved direction. Implementation is split into prerequisite slices.
|
||||
|
||||
Related:
|
||||
|
||||
- [Current roadmap](../../current_roadmap.md)
|
||||
- [Workflow API architecture](../../wf_api_architecture.md)
|
||||
- [Persisted run/resume contract](2026-06-03-persisted-run-resume-contract.md)
|
||||
- [Self-describing interrupt contracts](2026-07-01-self-describing-interrupt-contracts.md)
|
||||
- [Thesis system design](../../thesis/system-design-implementation.md)
|
||||
|
||||
## Purpose
|
||||
|
||||
Build one local-first web application that serves three related needs:
|
||||
|
||||
1. a reusable Workflow Console for inspecting a running `wf` JSON-RPC server;
|
||||
2. a reliable defense demonstration of the complete workflow lifecycle;
|
||||
3. a compact thesis presentation with live-demo and recorded-replay routes.
|
||||
|
||||
The application also demonstrates where an agent belongs in the product. A
|
||||
constrained agent translates a natural-language request into typed parameters
|
||||
for a prepared recipe. The workflow substrate remains responsible for drafts,
|
||||
artifacts, deployments, runs, interrupts, traces, validation, and source
|
||||
bindings.
|
||||
|
||||
The demo agent is an integration client, not new evidence for general agent
|
||||
planning ability. The audited challenge campaign remains the evidence for how
|
||||
generic external agents interact with the public product surface.
|
||||
|
||||
## Product Boundary
|
||||
|
||||
Create a top-level `web/` package rather than putting product code under
|
||||
`docs/presentation/`.
|
||||
|
||||
```text
|
||||
web/
|
||||
package.json
|
||||
astro.config.mjs
|
||||
src/
|
||||
pages/
|
||||
connect.astro
|
||||
console/
|
||||
demo/
|
||||
replay/
|
||||
presentation/
|
||||
appendix/
|
||||
components/
|
||||
agent/
|
||||
lifecycle/
|
||||
rpc/
|
||||
trace/
|
||||
workflow-graph/
|
||||
presentation/
|
||||
```
|
||||
|
||||
The first release is a local-development Workflow Console. It is not a
|
||||
production admin panel and does not claim authentication, authorization,
|
||||
multi-user administration, or safe access to arbitrary remote servers.
|
||||
|
||||
## System Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Browser[Astro and React UI]
|
||||
Routes[Astro server routes]
|
||||
Agent[DemoAgent service]
|
||||
Recipe[Prepared ReportRecipe]
|
||||
Job[LifecycleJob service]
|
||||
Rpc[WorkflowRpc service]
|
||||
Server[wf JSON-RPC server]
|
||||
Events[Job event stream]
|
||||
|
||||
Browser --> Routes
|
||||
Routes --> Agent
|
||||
Routes --> Job
|
||||
Agent --> Recipe
|
||||
Recipe --> Job
|
||||
Job --> Rpc
|
||||
Rpc --> Server
|
||||
Job --> Events
|
||||
Events --> Browser
|
||||
```
|
||||
|
||||
All workflow operations use the existing public JSON-RPC API. No Python-side
|
||||
demo endpoint, direct store mutation, or privileged workflow path is added.
|
||||
|
||||
The web app should not shell out to `wf` for normal operation. The CLI is an
|
||||
operator frontend: it resolves config, parses files and flags, formats output,
|
||||
and sometimes aggregates several calls for human convenience. The console needs
|
||||
the lower-level JSON-RPC request/response stream so it can show exact protocol
|
||||
evidence, avoid shell quoting and encoding failures, and keep raw calls aligned
|
||||
with interpreted UI state.
|
||||
|
||||
## TypeScript And Effect Boundary
|
||||
|
||||
Use Effect for server-side orchestration and protocol handling:
|
||||
|
||||
- `Schema` decodes JSON-RPC envelopes and selected result projections;
|
||||
- services and `Layer`s provide connection configuration, RPC, recipes, jobs,
|
||||
replay storage, and the model gateway;
|
||||
- tagged errors distinguish connection, protocol, decoding, workflow,
|
||||
timeout, and demo-state failures;
|
||||
- `SubscriptionRef` or `Stream` publishes lifecycle events;
|
||||
- scoped fibers run and cancel autoplay;
|
||||
- timeouts and retries apply only where semantically safe.
|
||||
|
||||
Do not spread Effect through every React component. React components consume
|
||||
ordinary view models and event streams. Astro route handlers are the
|
||||
`Effect.runPromise` boundary.
|
||||
|
||||
Mutation calls such as artifact creation, deployment saving, run start, and
|
||||
resume are never retried blindly. Health and idempotent read calls may use a
|
||||
small bounded retry policy.
|
||||
|
||||
## Connection Model
|
||||
|
||||
The connection page accepts a JSON-RPC URL such as
|
||||
`http://127.0.0.1:8765/rpc`.
|
||||
|
||||
1. The Astro server validates the URL.
|
||||
2. The first slice accepts only loopback hosts.
|
||||
3. `workflow.health` verifies the endpoint.
|
||||
4. The connection is retained for the browser session.
|
||||
5. Astro proxies JSON-RPC calls server-side to avoid browser CORS coupling.
|
||||
6. Every call records its raw request, raw response, interpreted result,
|
||||
duration, and equivalent CLI command.
|
||||
|
||||
Allowing arbitrary remote targets would turn the proxy into an SSRF surface and
|
||||
requires a separate security design.
|
||||
|
||||
## JSON-RPC Method Registry
|
||||
|
||||
Represent mapped operations declaratively. Each entry contains:
|
||||
|
||||
- JSON-RPC method name;
|
||||
- Effect schema for parameters and selected result fields;
|
||||
- human explanation;
|
||||
- equivalent CLI formatter;
|
||||
- interpretation function;
|
||||
- mutation/idempotency classification.
|
||||
|
||||
The initial read surface maps:
|
||||
|
||||
- `workflow.health`;
|
||||
- source list, inspect, and diagnose;
|
||||
- capability list and inspect;
|
||||
- draft-workspace list, get, validate, and compile;
|
||||
- artifact list and inspect;
|
||||
- deployment list, inspect, and validate;
|
||||
- run list, inspect, and trace.
|
||||
|
||||
The prepared demo additionally maps:
|
||||
|
||||
- draft-workspace create from capability and patch;
|
||||
- draft validation and compilation;
|
||||
- artifact creation from a workspace;
|
||||
- deployment save and validation;
|
||||
- run start, inspect, trace, and resume.
|
||||
|
||||
Mapping a method does not grant special authority. The Workflow Console and the
|
||||
prepared demo are ordinary users of the same registry.
|
||||
|
||||
## Workflow Console
|
||||
|
||||
The first console is read/inspect-focused. It provides:
|
||||
|
||||
- source and capability inventory;
|
||||
- draft workspace list, graph, revision, and diagnostics;
|
||||
- artifact versions and required source bindings;
|
||||
- deployment binding and readiness state;
|
||||
- run status, output, interrupt, and bounded trace;
|
||||
- raw JSON-RPC request/response drawers.
|
||||
|
||||
Generic visual workflow editing is not part of the first initiative. The
|
||||
prepared demo performs controlled mutations through the same public RPC
|
||||
registry. A future editor can reuse the graph and inspector components.
|
||||
|
||||
## Visual Interaction Model
|
||||
|
||||
The UI uses focus modes instead of showing every panel simultaneously:
|
||||
|
||||
- **Lifecycle:** Draft, Artifact, Deployment, Run, and Trace records.
|
||||
- **Graph:** interactive workflow graph with semantic zoom.
|
||||
- **Execution:** active nodes and trace progression over the same graph.
|
||||
- **Output:** rendered readiness report and created issues.
|
||||
- **Raw:** collapsible JSON-RPC request and response drawer.
|
||||
|
||||
Use an interactive graph component, expected to be `@xyflow/react`, inside an
|
||||
Astro React island. Static presentation diagrams remain Mermaid.
|
||||
|
||||
A small graph embedded in a lifecycle card can expand into the primary canvas.
|
||||
Selecting a node opens a side drawer with capability, source, bindings,
|
||||
outcomes, and trace data. Selecting a lifecycle record zooms back out.
|
||||
|
||||
## Lifecycle Job And Autoplay
|
||||
|
||||
The agent calls one macro tool. The macro creates a lifecycle job and returns a
|
||||
job id. The TypeScript job then executes public JSON-RPC operations.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor User
|
||||
participant Agent
|
||||
participant Macro as create_workspace_report
|
||||
participant Job as LifecycleJob
|
||||
participant RPC as Workflow JSON-RPC
|
||||
participant UI
|
||||
|
||||
User->>Agent: Request readiness report
|
||||
Agent->>Macro: Typed recipe parameters
|
||||
Macro->>Job: Create operation queue
|
||||
Macro-->>Agent: job id accepted
|
||||
Job-->>UI: Switch to lifecycle view
|
||||
loop Autoplay operations
|
||||
Job->>RPC: Execute next public operation
|
||||
RPC-->>Job: Raw result
|
||||
Job-->>UI: Event, reason, raw data, interpreted data
|
||||
end
|
||||
Job-->>UI: Pause for typed approval
|
||||
User->>Job: Approve selected issues
|
||||
Job->>RPC: Resume run
|
||||
RPC-->>Job: Final report and trace
|
||||
Job-->>Agent: Structured completion result
|
||||
Agent-->>User: Summarize result
|
||||
```
|
||||
|
||||
Autoplay:
|
||||
|
||||
- advances one operation at a time;
|
||||
- allows Pause and Next;
|
||||
- pauses automatically on errors, interrupts, and completion;
|
||||
- never approves a human interrupt automatically;
|
||||
- supports no backward step in live mode;
|
||||
- supports previous, next, and timeline scrubbing in replay mode.
|
||||
|
||||
The chat collapses while the lifecycle and graph views carry the operation. It
|
||||
returns after completion, when the agent summarizes the structured result.
|
||||
|
||||
## Attribution And Honesty
|
||||
|
||||
The UI distinguishes agent activity from orchestration activity.
|
||||
|
||||
- Agent card: `create_workspace_report({...})`.
|
||||
- Orchestrator card: concrete JSON-RPC method, reason, equivalent CLI, raw
|
||||
response, and interpreted result.
|
||||
|
||||
Do not present orchestrated sub-operations as independent agent tool calls. Do
|
||||
not present recorded text as a live model response. Replay mode is visibly
|
||||
labeled.
|
||||
|
||||
## Demo Agent
|
||||
|
||||
The agent is intentionally constrained:
|
||||
|
||||
- one prepared report recipe;
|
||||
- typed recipe parameters;
|
||||
- one macro tool;
|
||||
- no shell, repository reads, code search, or subagents;
|
||||
- bounded output and timeout;
|
||||
- replaceable model gateway;
|
||||
- recorded replay fallback.
|
||||
|
||||
The first model gateway may use the OpenCode API directly, but the application
|
||||
depends only on a `DemoAgent` service contract. Exact provider selection belongs
|
||||
to the agent-integration slice.
|
||||
|
||||
The demo agent is not compared with the benchmark agents. Benchmark agents test
|
||||
public-surface discovery and free-form operation; the demo agent illustrates a
|
||||
product integration built on that surface.
|
||||
|
||||
## Prepared `lda.chat` Report Workflow
|
||||
|
||||
Create a separate example rather than expanding the existing minimal report
|
||||
case study:
|
||||
|
||||
```text
|
||||
examples/lda_report_workflow/
|
||||
documents/
|
||||
project-brief.md
|
||||
architecture-notes.md
|
||||
evaluation-findings.md
|
||||
risk-register.md
|
||||
roadmap.md
|
||||
document_source.py
|
||||
report_source.py
|
||||
issue_board_source.py
|
||||
workflow.plan.json
|
||||
run-input.json
|
||||
wf.config.json
|
||||
```
|
||||
|
||||
Python sources:
|
||||
|
||||
- `local.lda_docs`: list and read deterministic project documents;
|
||||
- `local.lda_report`: analyse documents, combine findings, classify risks,
|
||||
render, and finalise the report;
|
||||
- `local.issue_board`: create, list, and reset local demo issues.
|
||||
|
||||
The issue board is JSON-backed with atomic writes. It is a deterministic local
|
||||
demo source, not a production tracker.
|
||||
|
||||
Workflow shape:
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
List[List lda.chat documents]
|
||||
Each{For each document}
|
||||
Analyse[Analyse document]
|
||||
Combine[Combine findings]
|
||||
Risks{Material risks found?}
|
||||
RiskSection[Build risk section]
|
||||
NoRisks[Record no material risks]
|
||||
Render[Render readiness report]
|
||||
Review[Typed issue-review interrupt]
|
||||
Selected{For each selected issue}
|
||||
Create[Create issue]
|
||||
Finalise[Finalise report]
|
||||
Revision[Record revision request]
|
||||
|
||||
List --> Each
|
||||
Each -->|loop| Analyse
|
||||
Analyse --> Each
|
||||
Each -->|done| Combine
|
||||
Combine --> Risks
|
||||
Risks -->|yes| RiskSection
|
||||
Risks -->|no| NoRisks
|
||||
RiskSection --> Render
|
||||
NoRisks --> Render
|
||||
Render --> Review
|
||||
Review -->|submitted| Selected
|
||||
Review -->|cancelled| Revision
|
||||
Selected -->|loop| Create
|
||||
Create --> Selected
|
||||
Selected -->|done| Finalise
|
||||
```
|
||||
|
||||
The report is titled **lda.chat Thesis And Project Readiness Report** and covers
|
||||
achievements, architecture status, evaluation evidence, material risks, and
|
||||
next actions.
|
||||
|
||||
The interrupt request includes the rendered report and proposed issues. The
|
||||
resume payload contains approval, selected issue ids, and an optional comment.
|
||||
The UI selects all issues by default and allows individual deselection.
|
||||
|
||||
## Self-Describing Interrupt Dependency
|
||||
|
||||
The current interrupt payload exposes `kind` and data but not a complete
|
||||
machine-readable response contract. The Workflow Console requires explicit
|
||||
request and resume schemas so it can render and validate arbitrary interrupts
|
||||
without reading workflow code.
|
||||
|
||||
The prerequisite contract is defined in
|
||||
[Self-describing interrupt contracts](2026-07-01-self-describing-interrupt-contracts.md).
|
||||
|
||||
## Replay And Failure Handling
|
||||
|
||||
Every lifecycle event envelope records:
|
||||
|
||||
- operation id and stage;
|
||||
- JSON-RPC method and parameters;
|
||||
- raw response or error;
|
||||
- interpreted result;
|
||||
- equivalent CLI;
|
||||
- reason and duration;
|
||||
- resulting lifecycle ids.
|
||||
|
||||
Recorded mode replays these same envelopes. Live failure offers a visible switch
|
||||
to the matching recording. The presentation does not restart in a different UI
|
||||
or hide the failure.
|
||||
|
||||
## Defense Presentation
|
||||
|
||||
The defense has 15 minutes of presentation and 15 minutes of questions. Target
|
||||
9-10 slides and no more than three minutes of live demo.
|
||||
|
||||
Routes:
|
||||
|
||||
- `/presentation`: primary slides;
|
||||
- `/demo`: live agent and lifecycle presenter;
|
||||
- `/replay`: recorded fallback;
|
||||
- `/appendix`: backup architecture, evaluation, and implementation slides.
|
||||
|
||||
The presentation transitions directly into the demo and back. The exact slide
|
||||
library is selected in the presentation slice; the route and shared component
|
||||
boundaries are fixed by this design.
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. Self-describing interrupt request/resume contracts.
|
||||
2. Deterministic `lda.chat` report workflow and Python sources.
|
||||
3. `web/` Astro and Effect foundation, connection flow, and RPC registry.
|
||||
4. Workflow Console read/inspect views, graph, trace, and raw drawers.
|
||||
5. Lifecycle job, autoplay, typed approval, issue board, and replay.
|
||||
6. Constrained demo agent and replaceable model gateway.
|
||||
7. Defense presentation and appendix routes.
|
||||
|
||||
Each slice gets its own executable implementation plan. Do not combine the
|
||||
Python contract change, web foundation, agent integration, and presentation
|
||||
into one implementation pass.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Production authentication or authorization.
|
||||
- Arbitrary remote RPC proxying.
|
||||
- A general visual workflow editor.
|
||||
- Scheduling or event triggers.
|
||||
- Google Drive, email, or other external service dependencies.
|
||||
- Free-form autonomous workflow synthesis in the live defense demo.
|
||||
- Treating the demo agent as benchmark evidence.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The initiative is complete when:
|
||||
|
||||
1. a local user can connect the console to a loopback workflow RPC server;
|
||||
2. lifecycle records and traces are readable without scrolling raw JSON;
|
||||
3. raw request/response evidence remains available beside interpretation;
|
||||
4. the prepared recipe runs through draft, artifact, deployment, run,
|
||||
interrupt, resume, issue creation, output, and trace;
|
||||
5. interrupt forms are generated from public contracts;
|
||||
6. live and replay modes render the same event model;
|
||||
7. the constrained agent invokes one macro tool and receives the final result;
|
||||
8. the three-minute demo has a tested replay fallback;
|
||||
9. the presentation explains the agent/substrate boundary without overstating
|
||||
autonomous planning.
|
||||
@@ -114,9 +114,10 @@ workflows as outcome-routed graphs and manages them through a
|
||||
Draft--Artifact--Deployment--Run lifecycle. A neutral source-provider boundary
|
||||
projects built-in, Model Context Protocol, and Python capabilities into the same
|
||||
workflow surface, while structured diagnostics and repair guidance support
|
||||
agent-operable authoring through CLI and JSON-RPC interfaces. Here, "AI Agent"
|
||||
names the agent-facing project context; the submitted implementation is the
|
||||
workflow substrate exposed to external agents.
|
||||
agent-operable authoring through CLI and JSON-RPC interfaces. An external agent
|
||||
interface can be layered over these operations; this thesis focuses on the
|
||||
lower-level substrate that makes such an interface useful rather than proposing
|
||||
a new autonomous planning algorithm.
|
||||
|
||||
The implementation is evaluated through automated conformance tests, a
|
||||
deterministic three-node report workflow, a browser-interaction workflow, and a
|
||||
@@ -140,13 +141,14 @@ comparison.
|
||||
|
||||
# Introduction
|
||||
|
||||
In the thesis title, "AI Agent" refers to the broader `lda.chat`
|
||||
agent-facing automation project. The submitted implementation focuses on the
|
||||
workflow substrate that such agents use: a typed runtime and lifecycle layer
|
||||
exposed through CLI and API surfaces. Experimental agent-harness work exists in
|
||||
adjacent project work, but it is outside the submitted implementation boundary;
|
||||
this report evaluates the substrate rather than claiming a production
|
||||
autonomous agent brain.
|
||||
`lda.chat` is positioned as an AI-agent-facing workflow platform. An agent
|
||||
interface can be implemented as a surrounding layer that combines a chat or web
|
||||
front end, a planner graph, and `wf` CLI/API operations exposed as tools. This
|
||||
thesis focuses on the workflow substrate beneath that layer: typed lifecycle
|
||||
records, source bindings, validation, execution, diagnostics, traces, and
|
||||
resumability boundaries. The contribution is therefore the infrastructure that
|
||||
lets external agents and human operators create reusable workspace workflows,
|
||||
not a new autonomous planning algorithm.
|
||||
|
||||
This report assumes a setting in which external LLM agents are used as workflow
|
||||
authors and operators, and asks what platform substrate they need for reusable
|
||||
@@ -172,7 +174,7 @@ Python source examples.
|
||||
**Scope of claims.** This report does not claim production security, broad or
|
||||
representative external-agent evaluation, arbitrary mid-node crash recovery,
|
||||
scheduling, role-based access control, general workflow parallelism, or a
|
||||
bundled autonomous agent brain. It reports a bounded, manually audited
|
||||
bundled autonomous planning layer. It reports a bounded, manually audited
|
||||
36-trial agent-operability campaign. Claims about planner efficiency remain
|
||||
design hypotheses: the campaign was not a controlled retry-reduction or token
|
||||
efficiency experiment.
|
||||
@@ -787,10 +789,13 @@ The implementation is organized into focused packages with clear boundaries:
|
||||
| `wf_platform` | Neutral source DTOs, source visibility, permission metadata, and policy |
|
||||
| `wf_artifacts` | Artifact, deployment, and run models; file-backed stores; validation |
|
||||
| `wf_api` | Application surface: capabilities, drafts, artifacts, deployments, runs |
|
||||
| `wf_config` | Neutral workflow configuration models and config loading |
|
||||
| `wf_server` | `WorkflowServer` composition from config, stores, and source providers |
|
||||
| `wf_transport_rpc_http` | JSON-RPC over HTTP transport for CLI and future clients |
|
||||
| `wf_mcp` | Legacy MCP frontend, broker/admin compatibility, and migration shims |
|
||||
| `wf_sources_mcp` | MCP upstream source implementation and persistent runtime pool |
|
||||
| `wf_sources_python` | Trusted in-process Python source loading and `NodeSpec`-to-`NodeDef` projection |
|
||||
| `wf_openapi` | Experimental OpenAPI source provider for typed HTTP operations |
|
||||
| `wf_cli` | CLI commands driving the JSON-RPC transport |
|
||||
|
||||
: Package responsibilities in the implementation. {#tbl:package-responsibilities}
|
||||
@@ -1034,6 +1039,16 @@ core provider-agnostic.
|
||||
|
||||
(Evidence: `src/wf_sources_python/`, `tests/wf_sources_python/test_loader.py`.)
|
||||
|
||||
## Experimental OpenAPI Source Provider
|
||||
|
||||
The repository also contains an experimental `wf_openapi` source provider. It
|
||||
parses OpenAPI documents, projects HTTP operations into typed `NodeSpec`
|
||||
contracts, and executes calls through HTTP request/response validation. This
|
||||
shows the provider boundary can extend beyond MCP and trusted Python sources,
|
||||
but it is not used by the thesis case study or agent challenge evaluation.
|
||||
|
||||
(Evidence: `src/wf_openapi/`, `tests/openapi/`.)
|
||||
|
||||
# Case Study: Deterministic Report Workflow
|
||||
|
||||
The thesis case study is a document/report preparation workflow backed by local
|
||||
@@ -1145,13 +1160,14 @@ wf draft create report_ws --capability local.report.extract_report
|
||||
|
||||
That command is intentionally a best-effort bootstrap, not a complete workflow
|
||||
synthesizer. Focused edit commands such as `wf draft set-name`,
|
||||
`wf draft set-input`, and `wf draft set-output` cover common schema and mapping
|
||||
edits without forcing an agent to write RFC 6902 JSON Patch by hand. Structural
|
||||
edits to an existing draft, such as adding `read_notes` before `extract_report`
|
||||
and `render_markdown_report` after it, still use `wf draft patch`. The
|
||||
raw-plan import path is the alternative route when the author already has a
|
||||
complete plan: it bypasses the draft workspace and creates the artifact
|
||||
directly.
|
||||
`wf draft set-input`, `wf draft set-output`, `wf draft bind`,
|
||||
`wf draft add-step`, `wf draft branch`, `wf draft handle`, and
|
||||
`wf draft set-workflow-output` cover common schema, mapping, step, and routing
|
||||
edits without forcing an agent to write RFC 6902 JSON Patch by hand. Raw
|
||||
`wf draft patch` remains the escape hatch for structural edits that focused
|
||||
commands do not yet cover. The raw-plan import path is the alternative route
|
||||
when the author already has a complete plan: it bypasses the draft workspace
|
||||
and creates the artifact directly.
|
||||
|
||||
The tested thesis path imports the complete three-node plan as an immutable
|
||||
artifact:
|
||||
@@ -1627,8 +1643,9 @@ deployment concerns beyond the controlled system-design evidence in this report.
|
||||
- **No visual workflow editor.** The platform is driven through CLI and API
|
||||
surfaces; no graphical editor exists yet.
|
||||
|
||||
- **No bundled autonomous agent brain.** The platform serves external agents;
|
||||
it does not include a built-in agent.
|
||||
- **External planner boundary.** The platform serves external agents through
|
||||
public workflow operations; an integrated autonomous planning layer is not
|
||||
part of the current prototype.
|
||||
|
||||
- **No general fork/gather.** Fork and gather workflow control is future work.
|
||||
|
||||
@@ -1660,17 +1677,19 @@ operational foundation or expands its feature scope.
|
||||
|
||||
## Longer-Term Capability Expansion
|
||||
|
||||
- **OpenAPI or fetch-style source provider.** Broader HTTP integration through
|
||||
a new source family, complementing MCP and Python sources.
|
||||
- **OpenAPI or fetch-style source provider stabilization.** The repository has
|
||||
an experimental OpenAPI source family; future work is hardening, operator
|
||||
documentation, auth integration, and broader HTTP coverage rather than the
|
||||
first proof of concept.
|
||||
|
||||
- **LLM nodes as typed source capabilities.** LLM calls exposed as
|
||||
`NodeSpec` contracts, allowing planners to compose LLM steps into workflows
|
||||
without making the core runtime model-aware.
|
||||
|
||||
- **Integrated agent harness.** Adjacent experimental work can be integrated
|
||||
once the substrate boundary is stable. That future layer would provide the
|
||||
autonomous planning loop that drives the workflow lifecycle; it remains
|
||||
outside the implementation and evidence claims of this report.
|
||||
- **Agent interface and planner loop.** Add a surrounding layer that combines a
|
||||
chat or web interface, a planner graph, and `wf` operations exposed as tools.
|
||||
This layer can drive the implemented workflow lifecycle without moving
|
||||
planning logic into the core runtime.
|
||||
|
||||
- **Scheduler and daemon operations.** Offline scheduling for deployments,
|
||||
cron-triggered runs, and server daemon lifecycle.
|
||||
@@ -1714,8 +1733,8 @@ demonstrates the architecture; the thesis contribution is the platform design
|
||||
and evidence that the design can work across multiple source families under
|
||||
controlled conditions. The implemented contribution is therefore the durable,
|
||||
typed workflow substrate required by an agent-facing automation system; the
|
||||
autonomous planning layer remains outside the submitted implementation
|
||||
boundary.
|
||||
agent interface and autonomous planning loop can be layered over it as future
|
||||
work.
|
||||
|
||||
<!-- References -->
|
||||
# References {#sec:refs .unnumbered}
|
||||
@@ -1786,8 +1805,10 @@ draft set-output report_ws --revision 3 --step call `
|
||||
--map title=state.title --map summary=state.summary
|
||||
```
|
||||
|
||||
Structural edits, such as adding `read_notes` before `extract_report` and
|
||||
`render_markdown_report` after it, use `draft patch` or a complete raw plan.
|
||||
For structural growth, prefer focused helpers such as `draft add-step`,
|
||||
`draft branch`, `draft handle`, and `draft bind` when they cover the intended
|
||||
edit. Use `draft patch` only as the low-level fallback, or import a complete
|
||||
raw plan when the full graph is already available.
|
||||
|
||||
## Draft Validation
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@
|
||||
{\Large\bfseries Design and Implementation of lda.chat:\par}
|
||||
\vspace{0.18cm}
|
||||
{\Large\bfseries An AI Agent for Automating and Creating Workspace Workflows\par}
|
||||
\vspace{0.45cm}
|
||||
{\small\itshape Implementation boundary: this thesis evaluates the workflow substrate used by external agents, not a bundled autonomous agent brain.\par}
|
||||
\vfill
|
||||
\begin{tabular}{@{}r@{\hspace{0.5em}}l@{}}
|
||||
External Supervisor: & \textbf{Eng. Trần Văn Trường}\\
|
||||
|
||||
@@ -43,6 +43,7 @@ Examples that belong in `wf_api`:
|
||||
`WorkflowRunSurface`
|
||||
- `WorkflowCapabilityApi`
|
||||
- `WorkflowDraftApi`
|
||||
- `WorkflowDraftAuthoringApi`
|
||||
- `WorkflowArtifactApi`
|
||||
- `WorkflowDeploymentApi`
|
||||
- `WorkflowRunApi`
|
||||
@@ -154,6 +155,7 @@ contract itself.
|
||||
WorkflowApi
|
||||
capabilities: WorkflowCapabilityApi
|
||||
drafts: WorkflowDraftApi
|
||||
draft_authoring: WorkflowDraftAuthoringApi
|
||||
artifacts: WorkflowArtifactApi
|
||||
deployments: WorkflowDeploymentApi
|
||||
runs: WorkflowRunApi
|
||||
@@ -164,6 +166,12 @@ they define application-facing response contracts consumed by multiple
|
||||
frontends. Internally, they should prefer typed models from `wf_core`,
|
||||
`wf_artifacts`, and `wf_platform`, then serialize at the boundary.
|
||||
|
||||
`WorkflowDraftApi` owns draft workspace lifecycle, validation, compilation,
|
||||
JSON Patch application, and focused low-level map edits. `WorkflowDraftAuthoringApi`
|
||||
is the semantic authoring layer above it: capability-aware bootstrap, bind,
|
||||
add-step, branch, handle, and remove helpers lower intent into ordinary draft
|
||||
workspace patches while preserving revision checks.
|
||||
|
||||
## Relationship To wf_core
|
||||
|
||||
`wf_core` is lower-level than `wf_api`.
|
||||
|
||||
Reference in New Issue
Block a user