Coding patterns
Architecture rules
engineowns workflow model rules, execution semantics, templates, and ports.providersis an adapter crate that implementsAiPortfor BYOK providers.orchestrationcomposes runtime, state, persistence, tools, projects, settings, and app services.desktopis only a transport adapter: Tauri commands and app bootstrap.uiowns rendering and interaction, via typed desktop invokes/events.enginemust not depend on HTTP clients, filesystem/tool I/O, Tauri, providers, orchestration, desktop, or UI.orchestrationcalls engine APIs; it never duplicates workflow validity or execution rules.- Add a port/trait only when a consumer is typed on it; otherwise call the concrete type.
- Existing boundaries:
engine/src/ports/(AiPort,ToolPort),providers/src/client.rs(AiClient), andui/src/api.ts(typed Tauri invoke/event wrappers).
Ownership by concern
| Concern | Source of truth |
|---|---|
Workflow types, defaults, WorkflowSettings | crates/engine/src/graph/workflow.rs |
| Graph validity and execution layer order | crates/engine/src/graph/validation.rs |
| Batch / headless run semantics | crates/orchestration/src/run/execution/headless.rs |
| Interactive pause/resume semantics | crates/engine/src/execution/interactive_engine/ |
| Node invocation and prompt assembly | crates/engine/src/execution/node_invocation.rs |
| Node templates, defaults, and locked fields | crates/engine/src/template/ |
LLM invocation contract (AiPort, AgentRequest) | crates/engine/src/ports/outbound.rs |
Tool execution contract (ToolPort) | crates/engine/src/ports/outbound.rs, crates/orchestration/src/run/execution/tool_port.rs |
| Human input and tool approval resume behavior | crates/engine/src/execution/interactive_engine/ |
| LLM transport mapping and tool-arg repair | crates/providers/src/mapping/, rig_adapter/ |
Provider client (AiClient, create_provider) | crates/providers/src/client.rs, lib.rs |
| UI desktop seam | crates/ui/src/api.ts |
| App backend composition and IPC surface | crates/orchestration/src/backend/mod.rs |
| Run execution, shared context, callable agents, execution cwd | crates/orchestration/src/run/execution/ |
| Mutable run/edit state transitions | crates/orchestration/src/run/state.rs |
| App workflow file store | crates/orchestration/src/adapters/storage/app_workflow_store.rs |
| Project metadata and workflow bindings | crates/orchestration/src/adapters/storage/project_store.rs |
Project workflow files (.flow/workflows/) | crates/orchestration/src/adapters/storage/project_workflow_store.rs |
| Saved agent definitions | crates/orchestration/src/adapters/storage/agent_store.rs |
| Skill discovery (read-only) | crates/orchestration/src/adapters/storage/skill_store.rs |
| Provider readiness and API-key resolution | crates/orchestration/src/settings/provider.rs |
| Settings persistence | crates/orchestration/src/adapters/storage/settings_store.rs |
| Tool registry and approval | crates/orchestration/src/tool/ |
| Tauri command/event surface | crates/desktop/src/lib.rs |
| Frontend invoke wrappers and UI state wiring | crates/ui/src/api.ts, crates/ui/src/context/ |
| Frontend DTO types | crates/ui/src/lib/types/index.ts |
| Editor layout and panels | crates/ui/src/screens/EditorScreen.tsx, crates/ui/src/panels/ |
| Sidebar and navigation | crates/ui/src/components/sidebar/ |
| Conversation and tool bubbles | crates/ui/src/components/conversation/ |
Runtime semantics
These live in crates/orchestration/src/run/** and crates/engine/src/execution/**, never in UI or desktop.
- Shared context:
WorkflowSettings.shared_contextis trimmed and appended to every node's system prompt for the run, and to ad-hoc/saved subagent prompts. - Execution cwd: the backend resolves it from the exact selected project's
default_execution_cwd(else project root). App workflow/chat runs get an isolated app-managed folder under{data_local}/openflow/workspaces/. Filesystem tools run there. - Callable agents:
AgentNodeConfig.callable_agents(orallow_all_callable_agents) is snapshotted at run start byengine::resolve_callable_agent_snapshotsintoCallableAgentrecords, the same type persisted agents use (orchestration::AgentDefinitionalias). Invoked via runtime builtinsopenflow_call_subagentandopenflow_declare_subagents. - Provider routing:
AgentNodeConfig.provider_idbeatsWorkflowSettings.provider_id, which beats the active settings provider. The run-scoped router sends eachAgentRequestto that provider; errors surface with no cross-provider failover. - Model default: at run prep, an empty
AgentNodeConfig.modelinherits the effectiveProviderProfile.default_model. An explicit node model always wins. - Workflow storage split: app-local workflows live in
workflows.json; project-linked workflows persist under{project}/.flow/workflows/.AppBackendmerges both on load. - Tool concurrency: shared tools may run in parallel within a batch; exclusive tools take a per-tool semaphore in
ToolPortImpl.
Persistence conventions
- All app persistence files live under
{data_local}/openflow/:agents.json,projects.json,workflows.json,settings.json,mcp-secrets.json. - Project workflow files use the
{workflowId}.workflow.jsonsuffix under.flow/workflows/. - Provider API keys persist in plaintext in
settings.json, on eachProviderProfile.api_key. The UI loads settings redacted and fetches keys over dedicated IPC. Env vars (OPENAI_API_KEY,ANTHROPIC_API_KEY, provider-specific ones) stay fallbacks. - MCP inputs and OAuth credentials persist in
mcp-secrets.json(plaintext, mode0600on Unix). MCP config stores only opaquemcp-secret:v1:*refs.
Implementation conventions
- Constants go at the top of the file, named by intent (
*_WIDTH,*_HEIGHT,*_GAP,*_PADDING). - Helpers sit near their use, private unless reused.
- Tests go in
#[cfg(test)] mod testsin the behavior's file. - Typed
thiserrorerrors with actionable messages. - Where order affects behavior, sort IDs for determinism (as in
validation.rsandrunner.rs). - Mutate state through dedicated
WorkflowRunState/AppBackendmethods, not direct map/vector edits across modules. - UI sidebar lists use the shared primitives (
SidebarNavButton,SidebarIconButton,SidebarList,SidebarListRow) for consistent hover/rename. - With no node selected, hide the inspector. The right column shows
WorkflowSettingsPanelorInspectorPanelby editor state.
Error handling rules
- Map external/system errors into local domain language at crate boundaries.
- Fallible operations return
Result<_, _>. No panics outside tests. expect(...)only for invariants a validated flow guarantees.
Test strategy
- New behavior gets focused unit tests in the same module.
- Test visible behavior, not private implementation details.
- For workflow logic changes, cover:
- validation outcomes
- execution layer ordering
- upstream input shape
- shared context injection
- callable agent snapshot resolution
- execution cwd resolution
- failure propagation
Testing workflows defines acceptance and live-AI checks. The architecture contract defines layer rules.
Dependency boundary
- Add workspace deps to the root
Cargo.tomlfirst, then to crate manifests. - Keep crate dependencies minimal and role-specific:
engine: graph, execution, templates, conversations, tools, and ports only.providers: HTTP + provider payload parsing/auth only.orchestration: runtime/state/persistence/execution.desktop: Tauri adapter only.ui: frontend rendering and interaction only.
Local run commands
| Task | Command |
|---|---|
| Start the desktop app | ./scripts/start.sh |
| Start the frontend only | npm --prefix crates/ui run dev |
| Typecheck the frontend | npm --prefix crates/ui run typecheck |
Test file layout
| Pattern | When | Example |
|---|---|---|
Sibling *_tests.rs | Large ported or multi-case suites | adapters/tool_impl/edit/patch_tests.rs declared in parent mod.rs |
Inline #[cfg(test)] mod tests | Small unit tests colocated with one source file | adapters/tool_impl/edit/io.rs |
Folder tests.rs | Integration tests for a module subtree | run/execution/tests.rs |
Declare sibling test modules in the parent mod.rs:
rust
#[cfg(test)]
mod patch_tests;One pattern per file: sibling file or inline block, never both.
Change checklist
- Edit the smallest owning module first.
- Add or update tests in the same PR.
- Run:
bash
cargo fmt --all --check
cargo clippy --workspace --all-targets
cargo clippy-max
cargo nextest run --workspace- If behavior contracts changed, update this doc,
AGENTS.md, andglossary.mdas needed.
