Skip to content

Platform design

Review the Xentropy service simulation design: workflow DAGs, service state, durable invocations, execution boundaries, and implementation requirements.

This document replaces earlier workspace/Prepare/Run architecture decisions. Keep all agent work aligned with it. The owner approved this design on 2026-10-09 and requested a clean replacement, without legacy fallback execution.

Product

xEntropy owns service-agent creation, workflow DAG composition, end-to-end test cases, and results. Workflows execute only in the browser or on the user's computer. Real nodes call real APIs directly; simulated nodes call hosted Eve APIs. No VM or sandbox runs the workflow. Eve handles every simulated application request using service instructions, files/software, and run-scoped state.

One workflow run equals one session. Each test case creates a fresh run. Service instances share state only when explicitly referenced by the same instance ID within a run. End the session on completion, failure, or cancellation; retain evidence, not reusable state. Interrupted runs can resume; abandoned runs expire after 24 hours.

Graph and tests

Use a dependency DAG with sequential chains, parallel branches, joins, nested bindings, and explicit real/simulated mode. No cycles, loops, conditional routing, or automatic real-to-simulated fallback. Test cases supply inputs, initial state/scenarios, mode overrides, assertions, and optional terminal nodes. Agents never receive expected outputs/assertions or unrelated service state. Treat service error outputs separately from transport/agent failures.

Shared interfaces (all work must use these)

Shared browser-safe types and validation live in src/graph/model.ts. Runner and API client live in src/graph/runner.ts and client.ts; local entrypoint src/graph/cli.ts. Server uses src/graph/server.ts, store.ts, eve.ts. Browser UI is frontend/pages/workflows.tsx, at /services.

Types: Json = null | boolean | number | string | Json[] | {[key:string]:Json}. ServiceDefinition: {id, revision, name, instructions, files: {path, content, encoding?: 'utf8'|'base64'}[], operations: {id, name, inputSchema?: object, outputSchema?: object}[], initialState: Json}. Workflow: {id, revision, name, services: ServiceDefinition[], nodes: WorkflowNode[], tests: TestCase[]}. WorkflowNode: {id, serviceId, operationId, instanceId, mode:'real'|'simulate', dependsOn:string[], input:Json, bindings: {target:string, source:string, path:string}[], real?:{url:string,method:string,headers?:Record<string,string>,secretHeaders?:Record<string,string>,timeoutMs?:number}}. Bindings use JSON Pointer; source '$input' or node ID, path into workflow input or node output. Dependency edges explicitly include node binding sources. Secret headers store environment-variable references, never values. TestCase: {id,name,input:Json,initialState?:Record<string,Json>,scenarios?:Record<string,string>,modes?:Record<string,'real'|'simulate'>,assertions: ({nodeId:string,path:string,equals:Json}|{nodeId:string,status:'executed'|'skipped'}|{nodeId:string,httpStatus:number})[],terminalNodes?:string[]}. NodeResult: {nodeId,httpStatus?:number,status:'running'|'passed'|'failed'|'skipped',input?:Json,output?:Json,error?:string,startedAt?:string,finishedAt?:string,source:'real'|'simulate'}. Run: {id,workflow:Workflow,testCase:TestCase,location:'browser'|'local',status:'running'|'passed'|'failed'|'cancelled'|'interrupted',nodes:Record<string,NodeResult>,createdAt,updatedAt}.

API prefix /v1/graph, management uses Clerk bearer or scoped runner token. GET /capabilities public. GET/POST /workflows; GET /workflows/:id. POST /runs {workflow,testCaseId,location} creates an immutable snapshot; a stable Idempotency-Key recovers the same admission after a lost response. Reusing that key with different input returns 409. Matching retries preserve terminal state and the original workflow revision. GET /runs and /runs/:id. PUT /runs/:id/nodes/:nodeId {result}; POST /runs/:id/finish {status}; POST /runs/:id/cancel. POST /runs/:id/invocations {nodeId,input} with Idempotency-Key; returns {id,status:'queued'|'running'|'completed'|'failed'|'cancelled'|'indeterminate',output?,error?}; GET /runs/:id/invocations/:id polls. POST /tokens {name,workflowId?} returns one-time runner token; DELETE /tokens/:id revokes; GET /tokens lists metadata. POST /runs/:id/heartbeat renews runner presence. No hosted real-call execution. Server owns simulated invocation outputs; other node observations are client-reported.

Runtime/storage

Use Clerk, Neon/Postgres, Vercel and production Eve (pinned independently of benchmarks). Durable Eve turns survive HTTP disconnection; idempotent admission avoids duplicate charges; never retry an uncertain dispatch blindly. Structured agent result {output:Json,state:Json} commits output/state atomically after validation. Serialize each service instance. Do not send assertions/expected outputs to Eve. Preserve account identities and historical evidence, but remove legacy execution paths and UI. Transactional database rows replace the global ledger owner lock for new runtime. No mock provider or fake success in production; test injection only.

Execution/security

Shared browser/local scheduler: bounded concurrency, correct dependencies, assertions, stop new work on failure, cancel outstanding simulation requests. Never silently retry real side effects. Local CLI resolves secret refs; browser refuses those and explains local-runner requirement. Keep user credentials out of graphs, exports, and evidence. Enforce account and token scopes, exact CORS origins, immutable run inputs, request/body bounds, budget admission and explicit errors. Poll long requests; no four-minute overall timeout. Default spending ceiling remains operator-configured, advertised in capabilities; no unpriced production invocation.

Delivery and acceptance

Save and edit graph/services/tests in the browser, export/import, run browser tests and the local CLI, inspect graph/node outputs and history. Each run has fresh simulated state. Test branches/joins/nested binding, recovery/idempotency, cancellation/budgets, account isolation and real failures. Run repository check/build/tests and browser tests; live Eve/Neon tests require actual configured services and must be reported separately. All work is on isolated /private/tmp/xentropy-service-graph, branch feat/service-graph-simulation. Do not change original dirty checkout. Commit/push/PR/merge only after integration verification and required review gates. No preview tabs or preview links.

Implementation refinements

  • Admission prices are integer micro-USD simulation credits. Monthly account and per-run limits are transactionally enforced; real-node observations are client-reported and never charged as inference.
  • Known local credential values in real-service responses must not leave the runner as evidence or downstream simulation input; fail explicitly rather than silently changing service semantics.
  • API and real requests reject redirects that could forward credentials. Network requests have bounded transport waits; the underlying agent work remains durable beyond HTTP connections.
  • Run history exposes interrupted state when browser/local heartbeats disappear; users can recover or cancel it. Real calls with uncertain outcomes are never replayed.
  • Ended sessions have cleanup retried by authenticated maintenance. Provider waits for human approval that the platform cannot fulfill become explicit request failures, never endless polling.

The public /gallery page links from the home page and navigation. Current graph templates are editable examples, not prerecorded successes. Forking creates a new workflow ID and revision 1. Individual Eve-simulated components copy their complete service definition into a draft, with fresh service/node/instance IDs and editable sample input. The editor can add components from the gallery or the account’s saved workflows without replacing the current graph. Copies do not retain upstream bindings or run state. Signing in from an anonymous draft preserves that draft; switching accounts or signing out clears private editor state. Save explicitly to persist a fork in the account; gallery actions never start inference.

Historical trajectories publish only the existing sanitized viewer JSONL and execution report from docs/evidence/workflow-demos, with clear earlier-runtime labels. They are never presented as executions of current templates. The platform reader preserves source record order and offers search, system-event filtering, pagination, and complete record expansion. Downloaded JSONL can also be uploaded to https://shekkizh.com/tools/agent-trace; that viewer has no general remote-file URL loader. Raw runtime archives and prepared workspaces are not published by the gallery.

Execution feedback

Disabled workflow actions show a visible, accessible prerequisite beside the control. Results include node errors, assertion comparisons, recorded execution events, and downloadable run evidence. Run.runnerErrors optionally stores bounded {nodeId?, message} diagnostics reported by the browser/local runner via the finish endpoint, including rejected requests before a simulation observation exists. These diagnostics do not replace server-owned node outputs or statuses. Runner diagnostics redact configured local secret values before transmission.