Desk
The remote desktop app made for iPhone Duo.
Governed, self-hosted AI agents: policy gate on every effect, hash-chained run ledger, approvals in Slack.
Translation pending
OtherGitHub @fuseone-ioOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
Governed AI agents for business operations: MCP tools, approval gates, audit ledger, budgets, channels, and customer-owned deployment.
Taken from the repository README
Loading the full README.
Read the full README ↗FuseOne Agents is a governed runtime and control plane for AI agents that work inside real business operations: reading systems, proposing actions, asking for approval when the risk calls for it, and leaving a traceable record of what happened.
It is built for agents that touch CRM, ERP, support queues, observability systems, internal APIs, secret stores and legacy tools. The product is not a generic chat shell and not a vendor connector marketplace. MCP servers, governed connector instances, channels and native platform tools are capabilities that must be scoped, classified and evaluated before they can change the outside world.
It installs into the customer's own environment. One binary, one PostgreSQL, one Helm chart.
| The trail is the record | A person decides what matters |
|---|---|
| Every step append-only and hash-chained; verifying recomputes the whole chain. | A write whose arguments derive from outside data stops for a person, with the rule named. |
More screens and the full product manual live in the documentation.
flowchart LR
accTitle: FuseOne Agents installation topology
accDescr: People reach the serving process. The worker plans with model providers and reaches business systems only after the Gate. Both processes share PostgreSQL and the content store.
subgraph outside["Outside the boundary"]
people["People<br/>browser, Slack, email"]
systems["Business systems<br/>CRM, ERP, observability, APIs"]
providers["Model providers"]
end
subgraph install["The customer's environment"]
subgraph binary["agentd — one binary"]
serve["serve<br/>HTTP, SSE, console"]
worker["worker<br/>leases runs, advances them"]
end
postgres[("PostgreSQL<br/>ledger, projections, config")]
content[("Content store<br/>arguments, results, answers")]
end
people --> serve
serve --> postgres
worker --> postgres
worker --> content
serve --> content
worker -->|"every call, after the Gate"| systems
worker -->|"planning"| providers
classDef store fill:none,stroke-dasharray:4 3
class postgres,content store
One binary, one PostgreSQL, one Helm chart. serve answers people and worker
advances runs; they are two commands of the same binary and share nothing but
the database.
Two stores, deliberately. The ledger is append-only and hash-chained, so it can never be edited — which is why the bulky, personal parts of a run live in the content store instead: tool arguments, tool results and closing answers are held by reference with a digest, under retention an erasure request can reach. A record that cannot be corrected must not be a record that cannot be emptied.
Nothing reaches a business system except through the Gate. The arrow from
worker to those systems passes seven deterministic checks first, and both the
decision and its rule are appended to the ledger before the effect happens.
Most automation platforms ask whether an integration can call an API. FuseOne asks a different question first: who decided this agent may do this thing, with this input, in this scope, at this cost?
The run ledger is the source of truth for execution. Projections make expensive questions fast to answer - cost, runtime health, memory, duplicate effects, simulation and trust - but they carry coverage, scope and provenance instead of pretending unknown is low or partial is complete.
The Gate's ruling is written before the effect happens. A grant can release an action that only needed approval; it cannot override a check that blocked it. Duplicate-effect recognition, memory, context sharing and connector calls all keep that same rule: the platform decides what can be said, read, skipped or written, and the model does not get to invent authority by text.
FuseOne can resume a run after a process or worker failure because the run is derived from its append-only ledger, not held in a worker's memory. Leases keep one worker on a turn at a time; an expired lease lets another worker fold the same steps and continue. Approval requests, parked runs, budget reservations and recorded tool calls therefore survive a restart.
That is durable agent execution, not a claim to be a general-purpose workflow engine. FuseOne interprets versioned agent definitions through one fixed run loop. It does not expose arbitrary deterministic workflow code, child workflows, general durable timers or a Temporal-compatible programming model.
Nor does durability make an external effect exactly-once. If a remote system commits a tool call and the worker dies before recording its result, FuseOne records the outcome as unknown and keeps the call's idempotency key. The tool or integration must still honor that key, be naturally idempotent, or offer a compensation. A model request can likewise be billed again if its response was not recorded before an ambiguous failure.
Use FuseOne for bounded agent investigations and actions that need Gate, labels, approval, budgets, memory and an auditable trail. Put a durable workflow engine beside it when the surrounding business process needs a general workflow language, long-lived timers, broad fan-out, workflow-level versioning or operational guarantees beyond the run loop FuseOne implements.
Public guide: Durable agent execution. Design boundary: NT-011.
Functional reference: docs/PRD-001-fuseone-agents.md.
helm install agents oci://ghcr.io/fuseone-io/charts/fuseone-agents \
--namespace fuseone --create-namespace --timeout 25m \
--set secret.existingSecret=fuseone-agents \
--set baseUrl=https://agents.example.com
--timeout 25m is not optional on an installation with memory to reconcile.
Helm defaults to five minutes and abandons the release when its hooks take
longer — the schema and the memory reconciliation both run as hooks, and no
chart can raise a client's timeout for it. Nothing is lost when that happens:
both hooks are resumable and running the command again continues where it
stopped. What is lost is the release.
Images are built in the open for linux/amd64 and linux/arm64, and signed
with no key at all - the signature's identity is the workflow that built it.
This runs inside your network where you cannot watch it build, so check it
before it does:
cosign verify ghcr.io/fuseone-io/fuseone-agents:<version> \
--certificate-identity-regexp '^https://github.com/fuseone-io/fuseone-agents/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
Installing, operating and proving it to an auditor: deploy/helm/fuseone-agents/README.md.
A release is a v-prefixed tag. make release V=x.y.z refuses a dirty tree,
runs the full local gate, creates the tag, and lets CI publish the versioned
image, latest, the OCI Helm chart, and a GitHub Release whose notes come from
the matching CHANGELOG.md section.
make dev # database, api, worker, console, and stand-ins for the model
# provider and an MCP server — everything, one command
make stop # end it, from any terminal
make reset # throw the development database away and start over
make dev prints where the console is and the setup token to claim the
installation with. Nothing external is needed: no API key, no network.
make check # build, vet, generated-code drift, tests, race
make check-pg # the same suites against a real PostgreSQL
make smoke # what the shipping binary serves, and what it refuses to
cmd/agentd/ the product: serve | worker | start | bootstrap | keygen | migrate
cmd/devstack/ local stand-ins for a model provider and an MCP server
internal/
domain/ core types. No I/O, stdlib only
ledger/ the append-only hash-chained ledger and its projections
gate/ deterministic checks and verdicts before external effects
engine/ the loop: fold the ledger, decide the next action
worker/ leases runs and advances them
model/ provider adapters, prices and prompt assembly
tools/ MCP catalogue, reservations, cache, egress and invocation
connectors/ governed connector shapes and catalogue entries
connectortools/ runtime bridge for governed connector instances
memory/ governed memory assertions, suggestions, labels and retention
dedupe/ cross-run duplicate-effect recognition
contextshare/ named artifacts shared between runs and agents
finops/ spend projections and aggregates
channel/ channel inbox, delivery, reporter and operational evidence
admin/ what operators change, and the record that they did
auth/ OIDC, sessions, delegation
httpapi/ HTTP + the OpenAPI contract's implementation
api/ openapi.yaml — the contract both sides are generated from
web/ the console: React 19 + Vite + shadcn/ui
docs/ PRD, data protection, operator docs, notes and manual pages
Every consequential decision here has a note arguing it, including what it gives up. They are worth more than the code comments for anyone deciding whether this design fits their problem.
| PRD-001 | What the product is, requirement by requirement |
| DP-001 | What is stored, what leaves the installation, and what can be erased |
| OP-001 | Installing it, the decisions an operator owns, and what to expect when something is wrong |
| NT-001 | Where MCP ends and integration begins |
| NT-002 | The remaining product work and why it is ordered that way |
| NT-003 | Authoring an agent by conversation |
| NT-004 | What the ledger costs at volume, measured, and why it is partitioned on the run's opening time |
| NT-005 | Channels, and why Slack and WhatsApp are two products |
| NT-006 | Evaluating agents, and why not to adopt a harness |
| NT-007 |
Engineering rules are in CLAUDE.md for the Go core and web/CLAUDE.md for the console. Design notes and commits are in English so public review has one shared language. The product manual lives in docs/manual and is bilingual where the console needs it.
| A canvas that authors the stages, without the specification becoming a picture |
| NT-008 | The tool servers to ship, chosen by shape and never by vendor |
| NT-009 | First-party connector shapes, and why runtime comes only after governance |
| NT-010 | Topology, the run loop, layering and where data is written |
| NT-011 | The durable run boundary, and when a workflow engine belongs beside it |
| NT-012 | Governed Slack tickets and Gravitee subscription approval |