One layer for workflows, agents and the people who sign off on them. Author on a canvas or in Python. Pause for a human - four minutes or four weeks - and resume exactly where you stopped, with the whole run signed.
Most platforms pick one: deterministic pipelines that can't reason, agent frameworks that can't be audited, ticket queues that can't execute. Lyhnis runs all three as first-class spans in one durable run - same retry semantics, same budgets, same signed record.
Canvas for the ops team, JSON for review, Python for engineering. Not three products - three renderings of the same graph, on the same engine.
@workflow(name="refund_authorization") def refund_authorization(invoice): doc = ocr.extract(invoice, schema="invoice.v2") if doc.total > 200: human.approval(to="#finance", expires="7d", escalate="cfo") result = agent.run("sonnet", tools=[refund_tool, ledger_mcp], budget="0.50usd") return stripe.refund(doc, note=result.summary)
External agents call your workflows as tools. Your workflows call external MCP servers as tools. The author defines the vocabulary - the agent may only speak it.
Drop a gate on any step. Approvers answer from wherever they already are, and the run wakes with actor, channel and source already recorded.
A workflow is a tool. A tool is a workflow. Nest them as deep as your problem needs - parent budgets roll up every nested agent's spend, every sub-workflow's tokens and every external call into one number per run.
Every activity is typed, retried, budgeted and logged before you write a line. Compose them, wrap them, or author your own - new activities and whole new categories get added on request.
Everything interesting about enterprise automation happens in the gap - between the machine finishing and the human deciding. Most engines lose that gap: a retry storm, an expired token, a queue drained on deploy. Lyhnis treats the pause as state. Restart the workers, ship a release, go home for the weekend; the run is exactly where you left it, and the resume is signed.
The pause lives in the engine's store - not in a worker's memory or a sleeping thread.
Slack, Teams, email or a magic-link on a phone. The gate doesn't care which one answers.
Expiry, escalation, quorum and step-up auth, declared per gate by the author.
Who approved, from where, at what second - written to the ledger, not to a log line.
One insert-only ledger for the whole execution layer. Every span - agent, human or system - signed, timestamped and tagged with its resolution source. Auditors get one row per answer, and they can export the lot.
The other half is the room you sit in on a bad afternoon: what ran, what it sent, what it produced, and which file came from where.
Volume, success rate, P95, queue depth and worker health - per activity and per tenant, Prometheus-backed, alertable anywhere.
Slack, Teams, email, Telegram - recipient, delivery state, content preview and a jump back to the exact step that sent it.
Uploads, sources, artifacts, datasets and templates - each tied to its uploader, its workflow and the activity that touched it.
Not a page in a trust centre written after the fact. Isolation, encryption, attribution and step-up auth are properties of the engine - which is why the audit is a query rather than a project.
EU or US residency per tenant, a DPA on request, and a published subprocessor list. Deletion is a request, not a support ticket.
EU residencyDPASubprocessorsMFA via TOTP or recovery codes, SSO over SAML and OIDC, step-up challenge on destructive actions.
MFASSOStep-upPer-tenant data and storage boundaries. Credentials encrypted at rest with Fernet, scoped per tenant, never in logs.
FernetPer-tenantInsert-only ledger with signed entries, actor typing and resolution source. Immutable and exportable.
Insert-onlySignedThe four most recent additions. Built in public, documented as we go - the changelog is the roadmap's receipt.
Workflows can call external MCP servers as tools. New MCP_OAUTH credential type, Fernet-encrypted and tenant-scoped; agent.run accepts server URLs in its tools list.
Agents can invoke other workflows as typed tools. The author defines the vocabulary; validation, HITL gates and audit are wired in at the workflow boundary.
Parent budgets now include every nested agent's spend, every sub-workflow's tokens and every external tool call. One number per run, top to bottom.
Every message a workflow sends, captured with recipient, delivery status, preview and a jump-back to the sending step.
Author in Python, test locally, deploy to the same engine the canvas uses.
Drag activities, place your approval gates, hit run. No local setup, same execution layer.
See the platform tour →