# Skaile Workspaces

The `@skaile/workspaces` npm package — the full Skaile agent runtime stack as one
published package. Every internal folder is exposed as a subpath export and the
`skaile` CLI ships as its `bin`, alongside sibling packages for the binding / plugin surfaces.

## Packages

| Subpath / Sibling | npm | What It Does |
|---|---|---|
| **core** | `@skaile/workspaces/core` | Shared types, manifest parsing, settings, store, framework config. Zero heavy deps. |
| **types** | `@skaile/workspaces/types` | Unified message types, event types, and runtime interfaces. The shared contract. |
| **bridge** | `@skaile/workspaces/bridge` | Pluggable agent driver abstraction. Backends: Claude SDK, Codex, OMP. |
| **flow engine** | `@skaile/workspaces/factory-assets/connectors/flow/engine` | Flow state machine with typed bindings, precondition admission, consumed-output validation, deterministic routing, active strict v2 agent/function/gate/router/sub-flow nodes, and legacy skill compatibility. |
| **flow contract** | `@skaile/workspaces/factory-assets/connectors/flow/contract` | Strict Flow v2 authoring schemas, v1 normalization, bounded expressions, binding origins, and canonical content identity. |
| **resolver** | `@skaile/workspaces/resolver` | Parses SKILL.md requirements (reads_from, writes_to), validates gates, generates agent preamble. |
| **client** | `@skaile/workspaces/client` | Framework-agnostic protocol client. Implements IAgentRuntime over a pluggable transport. |
| **transport** | `@skaile/workspaces/transport` | Transport adapters (WebSocket client/server). Pluggable — add stdio, IPC, etc. |
| **connectors** | `@skaile/workspaces/connectors` | Resource adapter infrastructure — unified access to git, postgres, redis, s3, sqlite, webdav, and more. |
| **session** | `@skaile/workspaces/session` | Session message dispatcher — bridges frontend subscribers with agent clients through a persisted message stream. |
| **runner** | `@skaile/workspaces/runner` | Headless agent runtime. Builds injected/native agent sessions, manages session state, executes flows via bridge. |
| **asset-manager** | `@skaile/workspaces/asset-manager` | Programmatic asset management API. Catalog, install / remove, workspace scaffolder. |
| **cli** | `@skaile/workspaces` (`bin: skaile`) | The `skaile` CLI binary — run skills, flows, manage projects. Also importable via the `@skaile/workspaces/cli` subpath. |
| **React bindings** | `@skaile/workspace-bridge-react` | `useAgentStore` + `useResourceClient` for React 18+. Separate npm package, lives at [`packages/bridge-react`](https://github.com/skaile-ai/workspaces/tree/main/packages/bridge-react) in this monorepo. |
| **Vue bindings** | `@skaile/workspace-bridge-vue` | `useAgentStore` + `useResourceClient` for Vue 3.3+. Separate npm package, lives at [`packages/bridge-vue`](https://github.com/skaile-ai/workspaces/tree/main/packages/bridge-vue) in this monorepo. |

Coding-agent plugin integration is **CLI-generated** — run
`skaile plugin install --driver <claude-code|omp|codex>`. There are no separate
plugin packages.

## Dependency Graph

```
cli  (top-level CLI — orchestrates everything below)
 │
 ├── runner          (headless runtime — session state, flow execution)
 │    ├── bridge     (pluggable LLM driver: Claude SDK, Codex, OMP)
 │    ├── transport  (WebSocket server transport for serve mode)
 │    ├── resolver   (skill requirements parsing + validation)
 │    ├── connectors (optional — external data backend access)
 │    └── core       (shared types, manifest parsing, store)
 │
 └── asset-manager   (asset management API + workspace scaffolder)
      └── core
```

**types** is consumed by bridge, client, transport, runner, cli, and the platform — it has no internal deps.

**client** + **transport** are consumed by the platform backend and any other agent consumer. Client depends only on types.

**session** wraps a client with persistence (MessageStore) and fan-out (SubscriberTransport). Consumed by the platform backend and forge apps. Depends on client + types.

**core** is the foundation — consumed by runner, asset-manager, cli, connectors, and ai-resource-manager.

## How They Interact

1. **User runs `skaile run <flow>`** → **cli** parses args, resolves the flow file, and delegates to **runner**.

2. **runner** loads the flow through the shared v2 parser, then the flow engine
   computes which agent, function, gate, router, and sub-flow nodes are available
   from completed/skipped state, hard edges, and deterministic preconditions.

3. Router frontier waves settle before other runtime work, select each first
   matching route, and prune only hard-flow-exclusive losing paths without an
   executor or model. Function nodes run with resolved bindings
   in the existing session workspace, gate nodes park for a human decision, and
   sub-flow nodes delegate inline. For an agent node, the flow connector presents
   its interpolated instruction, resolved values and origins, reusable asset
   requirements, and predecessor context to the session agent.

4. **bridge** starts the LLM backend (Claude SDK or Codex in-process, or OMP as a subprocess) and streams `AgentEvent`s (defined in **types**) back to the runner.

5. If the workspace has connectors declared (`skaile.yaml` `connectors` section), **runner** uses **connectors** to connect, mount, and inject tools before each flow execution.

6. **asset-manager** handles initial project setup (`skaile init`) — scaffolding directories, writing config files, and optionally building Docker images.

## Quick Start

```bash
# From the monorepo root
bun run cli --help          # run the skaile CLI
bun run cli skill list      # list available skills
bun run cli run mvp         # run a flow
```

Flow authors and editor integrations can import the v2 contract independently:

```ts
import {
  FlowDefinitionSchema,
  parseFlowDefinition,
} from "@skaile/workspaces/factory-assets/connectors/flow/contract"
```

Flow Engine v2 defines seven node kinds: `agent`, `subprompt`, `function`,
`check`, `gate`, `router`, and inline `sub-flow`. It
rejects unknown v2 keys with precise paths, and
normalizes recognized v1 definitions deterministically. Exact legacy sub-flow
nodes now activate, while every other legacy kind retains its existing
compatibility state trace.
Structured output references are checked against declared producer fields, and
gates carry a strict response schema. The generated schema is published as both
`contract/flow.v2.schema.json` and `contract/schema.json`.
Explicit legacy `type: skill` and exact `type: sub-flow` nodes normalize to
their executable v2 kinds; every other legacy kind remains an inert
compatibility placeholder with its IDs, parameters, assets, and dependency
semantics retained.
The runtime activates all seven kinds: `agent`, `subprompt`, `function`,
`check`, `gate`, `router`, and `sub-flow`.
Interpolated agent instructions, resolved values, and origins reach the session
agent through `build_handoff(nodeId)`; function and check nodes run shell,
Node, or Python commands in the existing session workspace without a model
turn, with resolved values exported as environment variables — a check's exit
status is a pass/fail verdict rather than a plain success/failure. Subprompt
nodes are `function`-shaped except for how the work runs: a second, isolated
`AgentDriver` instance per call, with no Skaile system prompt, no MCP servers, no connector capabilities, and no access to the session conversation, bounded to a single turn. It does retain the backend's own native tool surface (a coding backend keeps its file and shell tools, rooted at the session workspace) — isolation here means a separate conversation, not a sandbox, resolving its declared `run.model` tier via a pure
`resolveModelTier` against per-provider built-in tiers, failing the node
rather than substituting a model when a tier cannot be served. A declared output contract drives a JSON-response request and
response parsing through the same consumed-output validation every kind uses;
there is no corrective reprompt, so a parse or validation failure is an
ordinary node failure. A subprompt's output is classified agent-obtained, so a
downstream check always derives "asserted" provenance over it, never
"verified". That classification is transitive — every executed node persists
the origins it resolved on `NodeExecution.inputOrigins`, so a deterministic
node that carries an agent's value forward cannot launder it to
runtime-obtained, and a producer with no persisted origins (a run predating
the field) is read as agent-obtained rather than clean. Gate nodes
park immediately through the durable approval state, complete on approval, and
preserve rejection feedback for revision and a later approval re-request.
Router nodes evaluate ordered bounded expressions only after admission. The first
matching route wins; coordinated choices are retained across hydration, and only
hard-flow-exclusive losing paths are skipped while shared or externally live
convergence stays available. An unfinished declared output waits without
starving unrelated runtime work; possible branch targets stay off runtime and
agent availability until selection. Routers never invoke the session agent,
model client, or `NodeExecutor`. Sub-flow nodes load one child inline through the same session,
driver, `NodeExecutor`, gate operations, and `FlowAdapter` lifecycle. Parked approval and
input interactions are published on the parent sub-flow node, while the child
adapter remains transient and resumable in memory. Canonical flow identities,
cycle detection, and a depth bound keep resolution contained. Sub-flows create
no run group, loop behavior, second executor, child record, or new durable-state
field.
Downstream-consumed output schemas are enforced at completion. Agents receive one
durable corrective call; deterministic functions fail directly. Unconsumed schemas
remain prose-only.
Skills, connectors, mounts, MCP servers, and knowledge stay reusable
`run.assets` requirements, and shared refs are deduplicated in the dependency
graph. All seven current kinds — `agent`, `subprompt`, `function`, `check`,
`gate`, `router`, and `sub-flow` — are active.
`FlowDefinition` is the strict authored-v2 type; parser results use the wider
`ParsedFlowDefinition` so unknown legacy edge kinds and their metadata can be
retained inertly without weakening authored validation.
See the [Flow v2 authoring contract](../../docs/flow-v2-contract.md) for the
complete shape, evaluator bounds, generated JSON Schema, and content hash.

## Architecture Docs

- [Client-Server Architecture](../../docs/client-server-architecture.md) — design for the agent client, transport, and shared state protocol (new packages: `client`, `transport`)
- [Session Dispatcher Architecture](../../docs/sections/session/architecture.md) — design for session message dispatching, persistence, and fan-out (new package: `session`)

See each package's `CLAUDE.md` for architecture details and developer conventions.
