An agent that can install anything, call anything and write anywhere is only safe if the walls are real. In Kortix they sit below the agent, in the platform, where a prompt cannot talk its way past them.
One sandbox per session · Connector keys never enter it · Nothing merges itself
A session is not a tab in a shared runtime. It is a machine of its own, and the database will not let two sessions have the same one. Separating two of your own sessions is the same mechanism as separating two different customers.
inside one session
never crosses in
A tool needs a real credential to do real work, so the honest question is not whether the machine ever holds one. It is which machine holds which key, who decided that, and what never gets in at all.
01
Encrypted with AES-256-GCM under a key derived per project.
02
The person’s role and the agent’s declared grant must both allow it.
03
Placed in the session at boot, by name, on tmpfs at mode 0600.
04
The tool reads it from the environment. It is not written into the prompt.
05
The file is wiped on shutdown and the machine is destroyed with it.
Most AI tools give the agent whatever the person who started it can reach. Kortix does not. An agent identity carries its own policies, evaluated on their own, so it cannot inherit its way up to something you never granted it.
principal
resource type
Permissions attach to a principal, for an action, on a resource type.
Built-in roles — on every plan
account
project
Enterprise
Available on Enterprise, and on a self-hosted instance with an Enterprise licence. The built-in roles above are free on every plan.
A service account is a first-class machine identity the account owns, not a human token wearing a hat. Policies attach to it directly, and a request it makes is evaluated purely against its own policies — it never inherits the reach of whoever created it.
A person or a group can be narrowed to named agents and skills inside a project: marketing may use this agent and that skill, and nothing else. Anything you leave unscoped stays project-wide, so narrowing is something you opt into rather than something you have to undo.
Approval is not a setting buried in an admin panel. It is a block in kortix.yaml, versioned with everything else, that says which tool calls run, which stop for a person, and which are refused outright.
# reads run; writes and destructive calls stop for a humanpolicy: default_mode: risk policies: # a name-only rule cannot gate the target — conditions can - match: gmail.send_email action: require_approval conditions: - arg: to match: /@example\.com$/ # anything else through this tool is refused outright - match: gmail.send_email action: block # whole connectors can be gated with one glob - match: stripe.* action: require_approvalThree actions
always_run, require_approval, block. A rule matches a glob over fully-qualified tool paths, so one line can cover a single call or a whole connector.
Gate the target, not just the tool
"May the agent send email" is not a guardrail. Conditions match the arguments, so the rule can be "only to these addresses". An argument that cannot be evaluated fails closed.
No blanket "allow always"
Every gated call is approved on its own, with its arguments in front of you. There is no session-wide grant a later call with different arguments can hide behind — that shortcut was removed at the enforcement point, not just from the UI.
Set the default you want
default_mode: risk makes reads run and sends writes and destructive calls to a person. A project with no policy block keeps the permissive legacy default, so set this explicitly.
An agent can write as much as it likes on its own branch. Landing that work on main is a separate capability it does not have unless you hand it over deliberately — and handing it over is itself a change someone has to approve.
Every edit lands on the branch cut for that session. Nothing the agent does is visible to any other session, or to main.
When the agent wants something to survive the machine, it commits and opens a change request pointed at main. That is the only door.
A change request is a diff. An agent rewriting its own prompt is reviewed the same way a code change is — because it is one. A change request whose manifest does not validate cannot merge at all.
Merge is a capability of its own, refused to every agent unless an admin grants it. That grant lives in kortix.yaml — so an agent cannot widen its own reach without a change request someone else approves.
Every account action and every agent action is captured on every plan. The plan decides who may read, export, or stream that record — not whether it exists.
The same product ships as managed cloud, as a stack inside your own network, and as an isolated deployment. Open source, so what you are trusting is code you can read.
The managed service. We run the control plane and the compute; you run the company.
One Docker Compose stack on your box, from the same images the managed cloud runs. Your database and your files sit on disk you control.
A single-tenant deployment inside your own network. Air-gapped and other isolated topologies are scoped with us rather than self-served.
Where we actually stand
We do not hold ISO 27001 or HIPAA, and we do not imply that we do. When a report lands, this line changes that day and not before.
Please do not open a public issue for a vulnerability. Mail the security contact with the affected version or commit, the reproduction, and the impact.
Send the questionnaire, the architecture questions, the deployment constraints. We would rather answer them properly than have you guess from a marketing page.