human and machine actors.
Core Solution
Implementing a production-ready internal dashboard with integrated AI assistance requires a disciplined separation of concerns. The configuration model enforces this by isolating data connections, UI composition, agent orchestration, and lifecycle management into distinct YAML sections.
Step 1: Define Data Connections
Connections represent the boundary between the runtime and external systems. Each connection declares authentication, base parameters, and named queries. The runtime handles connection pooling, retry logic, and error serialization.
connections:
- id: warehouse_db
type: PostgresConnection
properties:
connectionString:
_secret: WAREHOUSE_DB_URL
queries:
- id: fetch_inventory
sql: SELECT sku, name, quantity, location FROM inventory WHERE active = true
- id: update_stock
sql: UPDATE inventory SET quantity = $1 WHERE sku = $2
params:
- name: new_quantity
type: integer
- name: target_sku
type: string
Architecture Rationale: Queries are defined at the connection layer, not the UI layer. This prevents UI components from constructing raw SQL and enforces schema validation at the boundary. Secrets are resolved at runtime via environment variables, keeping credentials out of version control.
Step 2: Compose the Interface
Pages are structured as trees of blocks. Each block declares its type, data source, and interaction handlers. Operators prefixed with _ replace imperative JavaScript expressions, enabling conditional logic, state binding, and data transformation within the configuration.
pages:
- id: inventory_dashboard
type: LayoutSidebar
properties:
title: Warehouse Operations
blocks:
- id: stock_grid
type: DataGridPro
properties:
rowData:
_request: fetch_inventory
columns:
- field: sku
header: SKU
- field: name
header: Product Name
- field: quantity
header: On Hand
cellStyle:
_conditional:
- condition:
_lt:
- _field: quantity
- 10
value: { color: red, fontWeight: bold }
- id: restock_form
type: FormPanel
properties:
fields:
- id: sku_input
type: TextInput
label: Target SKU
- id: qty_input
type: NumberInput
label: New Quantity
actions:
onSubmit:
- id: commit_update
type: ExecuteQuery
params:
connectionId: warehouse_db
queryId: update_stock
values:
- _state: qty_input.value
- _state: sku_input.value
confirm: true
Architecture Rationale: The _conditional operator handles styling logic without custom components. The confirm: true flag on the submit action enforces human approval for write operations, a critical safety mechanism for internal tooling. State binding via _state ensures form data flows directly into query parameters without intermediate transformation layers.
Step 3: Wire the AI Agent
Agents are declared as first-class configuration objects. They reference a model provider, define system instructions, and whitelist available tools. Tools are not custom functions; they are the same endpoints defined in the connection layer.
agents:
- id: logistics_assistant
type: ClaudeAgent
connectionId: anthropic_provider
properties:
model: claude-sonnet-4-5
instructions: >
You assist warehouse managers with inventory checks and stock adjustments.
Always verify SKU format before querying. Use tools only when explicitly requested.
tools:
- endpointId: fetch_inventory
- endpointId: update_stock
confirm: true
Architecture Rationale: The agent does not receive raw database credentials. It receives a scoped list of named endpoints. This enforces the principle of least privilege at the orchestration layer. The confirm: true flag on update_stock ensures the runtime pauses execution for human validation before applying changes, preventing automated drift or accidental data corruption.
Step 4: Attach Lifecycle Hooks
The runtime exposes six hook points in the agent execution loop. Each hook can trigger a standard endpoint, enabling audit logging, metric collection, or side-effect orchestration.
agentHooks:
- agentId: logistics_assistant
onToolCallFinish:
- id: log_agent_action
type: ExecuteQuery
params:
connectionId: audit_db
queryId: insert_agent_log
values:
- _agent: id
- _tool: name
- _timestamp: now
- _status: success
Architecture Rationale: Logging at the hook level guarantees visibility into agent behavior without modifying the model prompt or instrumenting the UI. The _tool and _agent operators provide contextual metadata that can be routed to centralized observability pipelines.
Pitfall Guide
1. YAML Indentation Drift
Explanation: YAML relies on whitespace for structure. A single misplaced space can silently alter document hierarchy, causing blocks to render incorrectly or connections to fail during compilation.
Fix: Enforce a strict 2-space indentation policy. Integrate yamllint into your CI pipeline with rules for indentation, truthy, and line-length. Avoid mixing tabs and spaces. Use editor plugins that visualize whitespace boundaries.
2. Operator Overload for Complex Logic
Explanation: Configuration operators excel at simple transformations and conditional rendering. Chaining multiple operators for nested business logic creates unreadable configurations that are difficult to debug.
Fix: Offload complex transformations to the connection layer. Pre-process data in SQL or apply mapping functions in custom plugins. Keep UI configuration focused on layout, binding, and user interaction.
Explanation: Granting an agent access to broad query endpoints or raw database connections violates security boundaries. The model may inadvertently trigger destructive operations or expose sensitive records.
Fix: Always whitelist specific, schema-validated endpoints. Never expose SELECT * queries to agents. Use parameterized queries with strict type constraints. Apply confirm: true to any endpoint that modifies state.
4. Ignoring Auth Context in Endpoints
Explanation: Endpoints defined in configuration execute with the runtime's default permissions unless explicitly scoped. This can lead to privilege escalation when internal tools are shared across teams.
Fix: Leverage _user and _session operators in connection configurations to enforce row-level security. Bind query parameters to authenticated user attributes. Validate permissions at the endpoint boundary, not the UI layer.
5. Skipping Audit Hooks
Explanation: AI agents operate asynchronously and can execute multiple tool calls per session. Without explicit logging, tracking agent behavior becomes retrospective and error-prone.
Fix: Implement onToolCallFinish and onFinish hooks for every production agent. Route logs to a dedicated audit table or observability platform. Include timestamps, tool names, input parameters, and execution status.
6. Assuming Type Safety
Explanation: YAML configuration lacks compile-time type checking. A mismatched parameter type or missing field will only surface at runtime, potentially causing silent failures or data corruption.
Fix: Validate payloads at the connection layer using JSON schema or database constraints. Use explicit type declarations in query parameters. Implement runtime validation middleware for custom plugins.
7. Treating It Like a Consumer UI Framework
Explanation: The configuration model optimizes for data density and operational efficiency, not pixel-perfect design or custom animations. Attempting to build consumer-facing interfaces results in brittle configurations and poor user experience.
Fix: Reserve this runtime for internal dashboards, admin panels, and ops tooling. Delegate consumer-facing applications to dedicated frontend teams using React, Vue, or Svelte. Use the configuration runtime as a backend orchestration layer if needed.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Internal CRUD / Admin Panel | YAML Configuration Runtime | 10:1 compression ratio, full Git traceability, rapid iteration | Low (self-hosted, no licensing fees) |
| AI-Augmented Operations | YAML Runtime + Scoped Agent Tools | Native endpoint integration, human-in-the-loop safety, unified audit trail | Medium (LLM API costs + hosting) |
| Consumer-Facing Product | Hand-Coded React/Next.js | Pixel-perfect control, custom animations, advanced state management | High (engineering hours, infrastructure) |
| Complex Custom Workflows | Hybrid (Config + Custom Plugins) | Balances rapid UI composition with JavaScript extensibility | Medium-High (maintenance overhead) |
| Enterprise Compliance | YAML Runtime + External Vault | Apache 2.0 license, self-hosted, auditable configuration diffs | Low (infrastructure only) |
Configuration Template
# lowdefy.yaml - Production Template
version: "5.3"
connections:
- id: primary_db
type: PostgresConnection
properties:
connectionString:
_secret: DB_CONNECTION_STRING
queries:
- id: list_records
sql: SELECT id, title, status, created_at FROM operations WHERE team_id = $1
params:
- name: team_id
type: string
- id: update_status
sql: UPDATE operations SET status = $1 WHERE id = $2
params:
- name: new_status
type: string
- name: record_id
type: string
agents:
- id: ops_coordinator
type: ClaudeAgent
connectionId: llm_provider
properties:
model: claude-sonnet-4-5
instructions: >
Assist operations teams with record lookups and status updates.
Always validate team_id before querying. Require confirmation for writes.
tools:
- endpointId: list_records
- endpointId: update_status
confirm: true
agentHooks:
- agentId: ops_coordinator
onToolCallFinish:
- id: audit_log
type: ExecuteQuery
params:
connectionId: audit_db
queryId: log_action
values:
- _agent: id
- _tool: name
- _timestamp: now
- _status: success
pages:
- id: operations_hub
type: LayoutSidebar
properties:
title: Operations Center
blocks:
- id: record_table
type: DataGridPro
properties:
rowData:
_request: list_records
params:
- _user: team_id
columns:
- field: id
header: ID
- field: title
header: Title
- field: status
header: Status
- id: status_editor
type: FormPanel
properties:
fields:
- id: status_select
type: SelectInput
label: New Status
options:
- value: pending
label: Pending
- value: completed
label: Completed
actions:
onSubmit:
- id: commit_change
type: ExecuteQuery
params:
connectionId: primary_db
queryId: update_status
values:
- _state: status_select.value
- _state: record_table.selectedRow.id
confirm: true
Quick Start Guide
- Initialize the project: Run the framework CLI to generate a base configuration file and local development server. The scaffold includes default connection templates and a sample page layout.
- Configure environment variables: Export database URLs, API keys, and LLM provider credentials to your shell or
.env file. The runtime resolves _secret operators at startup.
- Start the development server: Launch the local watcher. The server compiles the YAML configuration into a Next.js application and hot-reloads on file changes. Verify data connections and UI rendering in the browser.
- Build for production: Execute the build command to generate an optimized, stateless application bundle. Deploy the output to any Node-compatible host (Vercel, Docker, AWS Lambda, or Netlify Functions). The runtime requires no persistent server state, making horizontal scaling straightforward.