DocsProjects
Start here
Build and run
DocsReference
Projects
A project is the unit of isolation. Tools, credentials, the policy over their actions and the sandbox all belong to one, and nothing crosses between them by accident.
What a project holds
Every workspace starts with one project called Default, and most stay that way. The reason to add another is that two pieces of work should not be able to see each other: a client engagement and an internal tool, a production account and a staging one, a team that should not reach another team's Stripe key.
Who is on it
A project is public to the whole team, or private to the people named on it. Anyone in the workspace can create one, and whoever creates it is its first admin. A project's admins add and remove people, promote other admins, flip it between public and private, install and remove toolkits, and delete it. Organisation owners and admins reach every project by role, because somebody who can delete a project cannot meaningfully be hidden from it.
Installed tools
A toolkit is installed into a project rather than into the workspace. The same product can be installed in two projects, and those are two separate installs with separate configuration. An agent key that reaches only one of them cannot see the other, and a search run against one never returns the other's tools.
Credentials
The credential a toolkit authenticates with belongs to the project it was installed in. It is encrypted with AES-256-GCM before it is written, under a key that is separate from the one the auth system uses, and it is never returned to a client.
What the install allows
Each install decides which of its toolkit's actions are switched on, for everyone in the project at once. So the same product can be set up differently in two projects: every action on against the staging account, and everything that writes switched off against production, decided independently. A project's admins are the people who can change that, and everyone on the project can see it. See Access control.
The sandbox
Calls that need a runtime, which is CLI operations and stdio MCP servers, run in a persistent sandbox namespace belonging to the project. Two projects do not share a workspace on disk, so a file one of them writes is not a file the other can read.
Agent keys across projects
A key is granted a set of projects, or all of them. An all-projects key is a standing flag rather than a list of rows, so it picks up a project created after the key was issued. A key granted a specific set reaches exactly that set, and a key left holding none is inert rather than falling back to the whole workspace.
Whatever the grant says, a key is intersected with the projects its owner can reach at the moment of the call. Take somebody off a private project and it drops out of their keys on the next call, over a raw key and over a signed-in connector alike. A key can also be narrowed further, to particular toolkits inside a project and to particular actions inside a toolkit; a key with no narrowing in a project reaches everything installed there.
When a key spans several projects, the gateway names them in the instructions it returns on initialize, and the bridge tools take a project argument. That argument is only required where it decides something: when the same tool name is installed in more than one of the projects the key can reach, the runner says so and lists them rather than guessing.
Slugs and renaming
A project has a URL-safe slug derived from its name. The slug is not decoration: it is what appears in the address of every project page, and it is what the gateway advertises to agents as the name of a project to call into.
That used to be frozen at creation. A project created as “New project” and named afterwards kept the slug new-project-4, and new-project-4 is what agents were told the project was called. One workspace had three of them, and its agent had to be handed a written mapping from slug to name to work at all.
Renaming a project now moves its slug to match. Nothing breaks when it does, because the old slug is recorded as an alias and keeps resolving.
Project renamed: New project 4 -> Onvo Lite
Slug follows: /app/projects/new-project-4
/app/projects/onvo-lite
Old slug kept as an alias, so both of these still reach the project:
the bookmark somebody saved
the "project": "new-project-4" an agent is still passing to a runnerA retired slug stays taken for as long as the alias exists, so it can never be reissued to a different project. Reissuing it would point one address at two projects and send somebody to the wrong one silently, which is worse than the collision suffix it saves.
Renaming back to a name a project used before lands on the slug it had then, rather than on a suffixed copy of it, because a project is never blocked by an alias it already owns.