Keep your code and keys in your own cloud account
Last updated
Two ways to run an agent
An AI coding agent reads a ticket, copies your code, asks an AI model to write a change, and hands the change back for review. Someone has to provide the computer that does this. There are two common answers.
A hosted agent runs on the vendor's computers. You give it access to your code, and it copies your repository onto its servers. Model usage is usually billed through the vendor, often as credits, so you pay their price for it, not your model provider's. Your code, the model's output and the logs of every run live in the vendor's systems, under their security, retention rules and staff access.
An agent in your own cloud account does the same work on computers you own. A cloud account is the billing and security boundary your company already has with its cloud provider: the place your servers, databases and keys live, and whose access you already control. The agent's virtual machines (rented computers that start, do one job and shut down) run there. They use your own API key (the password that lets software call an AI model) with your AI model provider. The service that manages the agent stays outside, sending instructions in and getting short reports back.
The second setup takes a little more work up front, because you have to connect a cloud account. In return, your code and your key never live on the service's computers, and you pay your cloud and model providers directly, at their prices.
What lives where
It helps to draw a line between two zones. On one side is your cloud account. On the other is the service: the scheduling, the checks, the GitHub connection and billing for the service itself.
- Your cloud account: the virtual machines that do the work.
- Your cloud account: a copy of your code, only while a run is going.
- Your cloud account: your AI model API key, in your secrets store.
- Your cloud account: the full logs of every run.
- Your cloud account: the compute and model bills, paid by you directly.
- The service: scheduling, readiness checks on tickets, its GitHub app, run summaries, and your subscription.
- Between them: the service starts runs through an access role you create, and gets a short summary back from each run.
Three things are worth calling out.
- Your code is copied only inside your account, onto a virtual machine that exists for one run and is deleted after it.
- Your model key sits in your account's secrets store (the locked place your cloud provider gives you for passwords and keys). The service can put a key there but can't read it back. More on that below.
- The service doesn't hold your code, but it isn't blind. It reads ticket text to decide whether a ticket is ready to work, and it connects to GitHub to add labels and hand out access. Anyone who tells you their service "sees nothing" is skipping the details.
Your code does still go to your AI model provider, because the model has to read it to change it. That happens under your own agreement with that provider, on your key, straight from your account. The agent service is not in the middle.
What crosses the line during a run
A map shows where things sit. A run shows what moves. Here is one ticket, start to finish, with the boundary between the two zones drawn across the middle.
- The service checks the ticket is clear enough to work on.
- It starts a virtual machine in your account, through the access role.
- The machine copies your repository and works on the change with your AI model provider, using your key.
- The machine inspects the change and opens a draft pull request on GitHub.
- Only a run summary crosses back to the service: the outcome, the pull request link, the cost and the timings.
The summary that comes back is metadata: which repository and ticket, how the run ended, the link to the draft pull request, what the model cost, how many turns it took, and how long each phase lasted. It doesn't contain your code or the change itself. The change goes to GitHub as a draft pull request, where your team reviews it like any other.
The full logs, which can include file names and command output, stay in your account. If the service shows you a log tail in its dashboard, it reads it from your account through the access role at the moment you look.
Technical detail: exactly what a run summary contains
In BacklogBeast, each run emits one summary event, even when it fails. Its fields are: the machine's ID and size, a run ID, the repository, the issue number, the outcome (pull request, blocked, no ticket, or failed), a short outcome detail, the pull request link, the exit code, the model cost in dollars, the number of model turns, which models the session used, how the session ended, and the time spent in each phase (setup, the model session and so on).
There is no diff, file content or prompt in it. The ticket's own progress notes and the outcome comment go on the GitHub issue, where your team can already see them.
Connecting with one access role
For the service to start machines in your account, it needs permission. There are two common ways to grant it, and one of them is much safer.
The risky way is to create a user for the vendor and give them a long-lived key for it. That key works until someone remembers to delete it, and if it leaks, whoever holds it gets in.
The safer way is an access role. A role is a set of permissions that a named outside party can borrow for a short time. The service asks your cloud provider for temporary credentials each time it needs to act. It gets them only if you've said that exact party may use the role. They expire on their own within hours. Nothing permanent is ever handed over, so there's nothing long-lived to leak.
BacklogBeast accepts roles only, never user keys. Connecting an account comes down to your account ID and one role that you create.
How the role is scoped
A role is only as safe as what it allows. BacklogBeast's role is generated from code and checked by automated tests, so the policy you paste in is the same one the tests check. It allows:
- Starting machines, but only with the agent's own machine template, network and permissions, all marked as belonging to the agent.
- Stopping machines that carry the agent's tag, and none of your others.
- Reading the agent's own logs, for the dashboard's log view.
- Writing your model key into one named slot in your secrets store.
It also carries an explicit deny: a rule that blocks reading any secret, which overrides anything else in the policy. Everything else in your account, such as your databases, your other servers, your other secrets and your billing settings, is out of reach.
Technical detail: trust, the external ID, and the worst case
Who may use the role. The trust policy names one role in the service's account (the launcher), not the whole account. It also requires an external ID: a random value unique to your Workspace. That stops a problem known as the confused deputy, where someone tricks a service into using another customer's role, because the service always presents your value and only your role accepts it.
Scoping. Every permission is limited by name prefix (ticket-agent), by a tag the agent puts on its own resources, and by region. Launching a machine is allowed only with the agent's own machine permissions, and only into the agent's network with the agent's machine template, all carrying the agent's tag. Handing permissions to a machine is limited to roles under the agent's own path. The key write is limited to one named parameter.
Setting up the agent's resources. The design also has the service create the agent's network, machine permissions and logs in your account through the role, as one deletable stack. Any role it creates must sit under a permissions boundary: a ceiling policy you can inspect, which the role cannot remove or change. That keeps anything created through the role from ending up with more power than the boundary allows.
If the service itself were compromised, an attacker holding this role could start the agent's machines (costing you compute, stopped by the time cap), and read or overwrite the agent's logs and its key slot. They could not read your model key, touch any other resource, or create an unrestricted role.
Your key: written, never read
Your AI model key is the most sensitive thing the agent uses. Anyone holding it can run up charges on your model account. So the rule is simple: the service can put the key into your account, and it can never take it out again.
- You paste your AI model key into the dashboard once.
- The service passes it straight through to the secrets store in your account. It keeps no copy and does not log it.
- If the service tries to read the key back, your account refuses: the access role explicitly denies reading secrets.
- At the start of each run, the agent's virtual machine in your account reads the key and calls your AI model provider.
This isn't a promise the service makes about its own behaviour. The refusal is in the role, in your account, so your cloud provider enforces it. If the service's code changed tomorrow, it still couldn't read the key, and you can check the rule yourself by opening the role.
In the dashboard the key only ever shows as "present" or "missing". To change it, you paste a new one over it.
Give the agent a key of its own, in a separate project or workspace at your AI model provider, with a hard monthly spend limit. The agent's code has to use the key to work, so the machine can read it. The spend limit is what caps the damage if that key ever leaks.
Technical detail: who can read which credential
| Credential | Where it lives | Who can read it |
|---|---|---|
| Your AI model key | Your secrets store, one named slot | The agent's machine role in your account only. The service can write it, not read it. |
| The service's GitHub app private key | The service's account | The service's launcher. It never enters your account. |
| Your access role | Your account | Used only by the service's launcher, and only with your external ID. |
On the machine, the model runs as a separate, unprivileged user that is blocked from the machine's own cloud credentials. It holds the model key, because it runs on it, but no GitHub token and no cloud credentials. For GitHub, the machine uses a short-lived token narrowed to the one repository being worked on.
The key passes through the service's API once, on its way into your secrets store. It isn't logged or stored there.
Disconnecting
Leaving should be as clear as joining. Because all access runs through one role that you own, cutting it off is one action on your side: delete the role. From then on, the service's requests for temporary credentials fail, and it can't start, stop or read anything in your account.
The tidy order is to disconnect in the dashboard first, so the service removes the agent's own resources, and then delete the role. If you delete the role first, access still ends at once. The leftover agent resources are then listed for you to remove yourself, since the service can no longer reach them.
- Click Disconnect in the dashboard.
- The service removes the agent's own resources from your account: its network, machine permissions and logs.
- You delete the access role in your account.
- The service has no access left. Its requests for credentials now fail.
Two other things are yours to tidy up, because they were always yours: your model key in your secrets store, and the GitHub app installation on your repositories, which you can remove from GitHub's settings. The draft pull requests the agent opened stay in your repositories, like any other branch.
Questions to ask any agent service
Whichever tool you pick, these questions separate a real "your account" setup from a hosted one described in friendlier words.
- Where is my code copied during a run? On their servers, or on machines in my account?
- Who holds my model key, and can they read it? Is that enforced by my cloud account, or only by their promise?
- Who bills me for model usage? My model provider directly, or the vendor, with credits or a markup?
- How do I grant access? A role with temporary credentials, or a long-lived key?
- Can I read the exact permissions? Is there an explicit deny on reading secrets?
- What comes back to them after a run? A summary, or the full logs and the code change?
- How do I leave? Is it one action on my side, or a support request?
In practice with BacklogBeast
BacklogBeast is built around this split. Its virtual machines run in your connected cloud account, on your AI model provider key, and you pay for compute and model usage directly. BacklogBeast's plans charge for the service, never for model usage or a markup on it. Connecting means your account ID and one access role, with no user keys accepted. The role is generated from code and checked by tests: it can start and stop only the agent's own machines, read only the agent's logs, and write your model key but never read it. Each run sends back a summary of outcome, cost and timings, while your code and full logs stay with you. The work ends as a draft pull request for a person to review. BacklogBeast never merges and never deploys.
To see how the other safeguards fit together, read Letting an AI agent open pull requests safely. To see how per-run caps keep model spend in check, read What an AI coding agent costs per ticket. If you'd like to try it on your own account, join the waitlist.