# An open-source cloud agent that opens a pull request you can merge

> A cloud agent that opens a pull request is worth the review only when the branch, the tests and the merge rule are real. Kortix is the open-source AI Operating System: your agents, their skills, your company memory, and every connector in one git repo you own, with the agents working on real cloud computers.

URL: https://cloudagentsguide.com/cloud-agents-that-open-a-pr

## What each one hands back, and who can merge it

What each vendor documents about its own handoff and merge step, checked in October 2026.

| | Kortix (recommended) | Cursor Cloud | Railway Cloud Agents | Qoder Cloud Agents |
| --- | --- | --- | --- | --- |
| what it hands back | A change request on the session branch, with the diff and tests | A pull request you merge, plus screenshots, video and logs | A running VM and a terminal session you connect to | Edits on the mounted checkout; a branch and PR only when asked |
| branch per task | Yes. The branch name is the session id. | A separate branch per run, then a pull request | One VM per agent, not one per task | One sandbox per session; a branch pushed when the task asks |
| approval before merge | Default-deny. Merge needs a grant that includes project.gitops.merge | Merge follows your Git host's rules, outside Cursor | No merge step. You push with the installed GitHub CLI | Merge stays on the Git host; gh opens the request when asked |
| open source | Yes | No, a closed hosted service | No, a hosted platform you rent | No, a closed managed runtime |

## The branch and the merge rule, in the docs

`git`

```
Each session works on its own branch.
A pushed branch stays in the repository after the session stops and after the session is deleted.
A change request merges one branch, the head, into another, the base.
An agent that declares kortix_permissions merges only when the grant includes project.gitops.merge.
A session cannot merge a change request it opened unless its grant in kortix.yaml includes project.gitops.merge.
Report the change request number to the person, and stop.
```

Source: https://kortix.com/docs/git

A session gets one branch, and an agent merges only when its grant includes the merge capability.

## What a pull request from an agent should contain

A pull request holds a branch, a diff, a review and a merge into a base branch at one address. When a cloud agent opens one, the branch is where the work sits and the diff is what a reviewer reads. The other two decide whether the change lands: what ran before the request appeared, and who is allowed to merge it.

Most vendor pages describe the first two and leave the rest to you. An agent that pushes a branch but cannot say which tests it ran has handed over a diff with no evidence behind it. An agent that can merge its own branch has removed the review the pull request was supposed to create.

Kortix gives every task its own machine and its own branch. One isolated sandbox per session. Each session has its own isolated machine and branch. The sandbox clones the project repo into `/workspace`, cuts a branch named after the session, and runs OpenCode inside that machine, so the agent works next to a real clone with the project's tools installed ([Agent Computer](https://kortix.com/agent-computer)). Nothing it installs or edits survives except the commits it makes.

## The life of one task, from prompt to merged

A session starts with a task and a base. Kortix cuts the branch from the session's `base_ref`, the project default branch unless the session was created against another one, and the branch name is the `session_id` with no prefix. Inside the sandbox that value is `$KORTIX_BRANCH_NAME`, and the agent commits there.

The handoff is a four step contract in the docs: commit on the session branch, run `git push origin HEAD`, open the change request, and report its number to the person. The last step matters for review. The agent stops once it has reported, so the default path leaves the merge with whoever reads the request ([Git](https://kortix.com/docs/git)).

A reviewer opens the change request and reads the unified diff, on the Review page or with `kortix cr diff`. Asking for changes is its own command. The note is recorded on the change request and sent back to the session that opened it as a new prompt, and a sleeping sandbox wakes to answer. The merge validates the manifest on the head branch, fast-forwards the base when the head is strictly ahead, and otherwise writes a merge commit.

Two refusals close the obvious holes. A head with no commits ahead of the base is refused, because an empty pull request is noise. A session that tries to merge its own change request without a merge grant gets `403 CR_SELF_MERGE_REFUSED`. Both errors reach the agent, so it can tell the person what is missing instead of retrying in silence.

## A real change request, opened by an agent and merged the next morning

Kortix's own repository runs this way. Change request 10001 is a performance fix in the API: two authorization reads, repeated inside one request, wrapped in a per-request memo ([pull/10001](https://github.com/kortix-ai/suna/pull/10001)).

```text
# github.com/kortix-ai/suna/pull/10001
perf(api): memoize share-subject + app access-grant reads per request (KRTX-2341)
author agent-kortix   base dev   head krtx2341-apps-5xx   7 commits
 apps/api/src/apps/access-grants-memo.test.ts        +100   -0
 apps/api/src/apps/access.ts                          +36  -17
 apps/api/src/connectors/share-subject-memo.test.ts    +88   -0
 apps/api/src/connectors/share.ts                      +21   -4
 tests/attestations/krtx2341-apps-5xx.json             +18   -0
 tests/attestations/krtx-1750-gateway-url.json           +0  -19
 6 files changed, 263 insertions(+), 40 deletions(-)
```

Most of the added lines are tests. The two new test files assert how many times a request reads the database, and the change request records the red run at the base commit (six pass, three fail) beside the green run at the head (nine pass). That is the evidence a reviewer needs before reading a line of production code, and it is on the request rather than in someone's memory.

The approval came from a separate review session, which re-ran the narrow tests at the head, checked three acceptance criteria, and recorded `founder_review: no`. The merge landed 44 seconds later. The account that opened the request is also the account that merged it, because in Kortix's own repository `agent-kortix` holds the merge grant. A project created from the starter starts in the same position: its `kortix` agent carries `kortix_permissions: all`, and `all` means every project permission, `project.gitops.merge` included ([Agents and permissions](https://kortix.com/docs/project/agents)). A team that wants the merge to stay with a person edits that grant in `kortix.yaml`, and the edit arrives as a diff like any other config change.

The product supports both outcomes, and the switch between them is a permission someone sets in the repository.

## The four controls a team needs

**Merge permission.** Session work reaches `main` through a change request. Merge is default-deny for agents. The grant is per agent, in `kortix.yaml`, and an agent with no `kortix_permissions` block cannot merge at all. A merge that also edits agents, the default agent or triggers needs the matching write permission, and no agent can grant a permission it does not already hold.

**Tool approval.** Approval gates you set. Off until you set them. A connector call can run, be held for approval, or be blocked, and a held call pauses the agent's turn until someone answers.

**Credentials.** The session token inside a sandbox reads the repository and pushes that session's own branch. Credentials for the upstream repository are added on the server, so they do not reach the machine.

**Audit.** The audit log records each clone and fetch as `git.clone` and each push as `git.push`. With the change request, a reviewer gets three linked records for one task: what the machine read, what it pushed, and who approved it.

## What separates a reviewed change from a demo

Four questions sort the field faster than a feature list. Does each task get its own branch, or do tasks share one checkout? Can the agent merge its own work, and where is that permission written down? Which credentials reach the sandbox, and who can read them there? What do you keep if you leave, a diff in your repo or an export request?

Open source. Read it, fork it, audit it. For a team that reviews code, the rules deciding the review are files in the repository being reviewed.

## Questions people ask before they trust a branch

Who opens the branch, who merges it, and how a person reviews it.

### Does a cloud agent open a pull request?

Yes, in products that give the agent a repository and a branch. A Kortix session commits on its own branch, pushes it, opens a change request toward the base branch, then reports the number and stops.

### Can an AI agent push to main?

Only through a change request, and only where the grant covers the merge. A Kortix session pushes its own branch; the starter's kortix agent is granted all, which includes project.gitops.merge, so a team that wants a person to merge narrows that grant.

### How do I review an agent's code change?

Read the diff and the tests it ran, then approve or ask for changes. A change request on Kortix carries both, and a request-changes note goes back to the session that wrote the code as a new prompt.

## Let an agent open the pull request. Keep the merge.

One session, one branch, one rule about who merges.

[Try Kortix](https://kortix.com) · [Read the docs](https://kortix.com/docs)

One isolated sandbox per session | Self-host is free | Open source. Read it, fork it, audit it.
