An operational ontology for your organization.
Worklet holds the things your organization works with, the teams that work on them, and the links between them, as one typed model. People, apps, and AI agents change it only in the ways you define, and each sees only what they may.
Describe your incidents, machines, customers, or documents as object types. Define the actions that change them and who may run each one. Access is set on the records themselves, and chat, files, search, and agents all follow it. Self-host it in one Docker container, or use the hosted service.
Already have an organization? Sign in · Quickstart · API reference
What Worklet does.
- Objects, teams, and linksObject types with typed properties and format rules, and link types between them with a cardinality. Teams are objects too: they can sit under each other, and memberships can end on a date.
- Actions change the dataAn action, such as "open a work order", takes typed inputs, checks its criteria, and applies all its edits or none. Owners grant each action to teams. Grant the action without edit rights, and it is the only way those teams change the records. Every application is in the audit log.
- Access follows the recordAccess is set per type, per object through the people and teams an object names (an assignee, an owner, a sharing list), and per property. A salary can be visible to HR only, on records everyone else sees.
- Timeseries on objectsSensor readings, metrics, or prices, stored as series attached to an object and read under that object's access: raw, in buckets, or the newest value, kept for as long as the retention you set. Totals across series, such as power per site, count only the series the reader may read.
- Chat, files, and searchChannels and direct messages, including a channel about one object that whoever sees the object can see. Folders and versioned files, where a folder hidden from someone hides everything under it. One search across all of it that finds only what the person searching could open.
- AI agents and MCPEvery organization has its own MCP server. Assistants act for a signed-in person within the scopes they granted, agents use scoped tokens, and neither gets more than the user it acts as. Connectors add tools from outside MCP servers, reviewed and granted to teams with limits on their arguments.
An access model that is checked, not just tested.
The access rules are a formally verified model, not the code directly. Machine-checked statements about that model show, for example, that one organization never sees another's data, that a hidden folder hides everything below it, and that search returns only what you could open. The server is tested against the model, and Postgres row-level security keeps every organization's rows apart underneath it.
- Scoped transactionsRequest handlers only ever get a transaction scoped to one organization, built from a verified credential.
- Row-level securityForced on every table, with the organization set per transaction and runtime roles that cannot bypass it.
- TestsTests write to every organization table and try to cross over; a table without the policy fails them.
How organizations are kept apart · Users, teams, permissions
A web app for the people, an API for everything else.
People browse and edit objects in tables and calendars, change the model, apply actions from generated forms, and follow the audit log and the live feed. The web app uses the same API as your agents and your own apps, so it shows each person exactly what they may see.


One incident, an agent, an assistant, and a person.
A machine breaks down. An agent account reports and assigns the incident, a technician's assistant does the work through MCP, and a supervisor approves it in the web app. Each step is an action the organization defined, checked against who is calling and what the data looks like when it commits.
- dispatch-bot · RESTAn agent account reports a hydraulic leak on Press 7 and links it to the machine.
201 incident - dispatch-bot · RESTIt applies assign_incident: an assignment is recorded and Tess is emailed.
201 applied - dispatch-bot · RESTIts answer is lost, so it retries with the same idempotency key.
200 replayed - Tess · MCPTheir assistant sees only the incidents assigned to them, and lists the actions they may apply.
1 incident visible - Tess · MCPIt tries to reassign the incident. Technicians are not granted that action.
403 forbidden - Tess · MCPIt opens a work order: the order, two links, the incident in progress, the machine in maintenance, in one transaction.
201 applied - Tess · MCPIt submits the close with the version it read before the work order changed the incident.
409 version_conflict - Tess · MCPIt reads the incident again and submits the close for approval.
201 awaiting approval - Tess · MCPIt tries to approve their own close of a high-severity incident.
422 criteria_failed - Sam · RESTThe supervisor, who watched every change on the event stream, approves. The incident is closed.
201 closed
The model changes while it runs.
Add a type or a property and use it at once. A new rule applies to every write at once and to stored objects in the background, with each object marked valid, invalid, or pending. Removing a property is instant, and its values never come back. Object types and actions keep every version, and each action application records the one it ran.
{
"api_name": "employee",
"display_name": "Employee",
"properties": [
{ "api_name": "name", "type": { "kind": "string" }, "required": true,
"rules": [{ "rule": "length", "min": 1, "max": 100 }] },
{ "api_name": "email", "type": { "kind": "string" },
"rules": [{ "rule": "email" }, { "rule": "unique" }] },
{ "api_name": "manager", "type": { "kind": "user_ref" } },
{ "api_name": "started", "type": { "kind": "date" } },
{ "api_name": "office", "type": { "kind": "geo_point" } },
{ "api_name": "badge", "type": { "kind": "string" },
"rules": [{ "rule": "validator", "name": "luhn", "version": 2 }] }
]
}{
"filter": { "op": "and", "filters": [
{ "op": "linked", "link": "projects", "object": "o9k3m7p1s5v2x6z0b4d8f2h6" },
{ "op": "gte", "property": "started", "value": "2026-01-01" },
{ "op": "not", "filter": { "op": "is_null", "property": "email" } }
] },
"order_by": { "property": "started", "direction": "desc" },
"limit": 50
}def validate(value):
digits = [int(c) for c in value if c.isdigit()]
if len(digits) != len(value) or len(digits) < 8:
return "badge numbers are at least 8 digits"
total = 0
for i, d in enumerate(reversed(digits)):
if i % 2 == 1:
d = d * 2 - 9 if d > 4 else d * 2
total += d
return total % 10 == 0id: 1042
event: object.created
data: {"type":"employee","id":"o4b8j2e6c0t1q5w9r3y7u2i6","version":1,"properties":{"name":"Ada"}}
id: 1043
event: link.created
data: {"link":"projects","from_type":"employee","from":"o4b8j2e6c0t1q5w9r3y7u2i6","to_type":"project","to":"o9k3m7p1s5v2x6z0b4d8f2h6"}
id: 1044
event: object.updated
data: {"type":"employee","id":"o4b8j2e6c0t1q5w9r3y7u2i6","version":2,"properties":{"name":"Ada","started":"2026-03-01"}}Rules too specific for a schema run as Python in a sandboxed interpreter with no filesystem, network, or imports, at most 250 ms and 32 MiB per call.
Use cases.
Each of these is usually its own app, with its own database, permission checks, and audit trail. In Worklet each is a model and a set of actions, used by the same people and agents under the same rules.
- Machine maintenanceIncidents, assignments, and work orders. Technicians see only the incidents assigned to them, and a high-severity close needs a second person.assigned access · actions · four-eyes approval · webhooks
- Document managementFolders and versioned documents shared with people and teams. Files are readable by whoever sees the document, and unsharing ends that at once.sharing lists · team access · attachments · version conflicts
- Car salesStock, leads, reservations, deals, and invoices. Salespeople see their own customers, a large discount needs a manager, and closing sells the car and emails a numbered invoice at once.custom formats · one-to-one links · sequences · emails to customers
- An agentic dev teamIssues, tasks, pull requests, and reviews for people and coding agents. Agents claim work and spend their own budgets; CI reports back through signed webhooks.races · private budgets · review policy · webhooks in and out
- Smart home and householdDevices, scenes, chores, and a maintenance calendar. A hub agent carries out changes, schedules add the recurring work, and a guest’s access ends with the stay.scheduled actions · expiring memberships · automations · calendars
- Your ownDefine your own types, rules, and actions in the web app or through the API, start small, and reshape them whenever you need to.web app · API · versioned changes
Hosted or self-hosted.
The same server either way: one Rust binary on Postgres, with the web app.
What it is not.
- Not an agent runner.
- Worklet does not run agents or call models. Your agents connect over MCP or the REST API and are checked like anyone else.
- Not a data warehouse.
- Objects are JSON documents checked against their types, queried with typed filters. Run analytics elsewhere.
- Not a sandbox for agent-written server code.
- Isolation keeps a buggy handler inside its organization. Server code an agent writes needs review like any other change.
- Not finished.
- Access goes down to single objects and properties, but not along links, and property filters are not indexed yet. See current limits and measured performance.