An agent that builds an internal tool will eventually want to deploy it, and the easy path is an access key on the laptop. Here is how to narrow that on plain AWS and how Encore moves cloud access off the agent.
An agent building an expense approval tool will reach a point where the code works locally and the next step is AWS. If there is an access key in ~/.aws/credentials, a capable agent will use it, because nothing tells it not to. That key usually belongs to a developer with broad rights, so the agent can now do anything that developer can do in the account.
This guide looks at what that exposes and at two ways to keep the agent productive without it.
An access key is not scoped to a task. When Claude Code runs aws commands, it runs them with the developer's identity, and Claude Code's permission settings can allow or deny tools but cannot tell which IAM actions a shell command will make. The OWASP entry on excessive agency describes this failure mode: the model has more permission than the task needs, so a wrong step has real effects.
For internal tools the risk is sharper, because the tool exists to reach business data. An agent wiring a dashboard to the orders database with an admin key can also modify the security group that protects it.
The standard approach follows AWS IAM best practices: temporary credentials through roles instead of long-lived keys, with least privilege as NIST defines it. In practice:
CLAUDE.md or AGENTS.md that it writes infrastructure code but never runs apply.This works and many teams run it, although every internal tool needs infrastructure code that someone reviews, and the agent writes IAM policies and networking it cannot test before CI runs. The rules file is guidance only, so a key that is still on the machine remains usable.
Encore combines an open source SDK, in which a TypeScript or Go service states the databases, topics, cron jobs and secrets it uses, with a platform that provisions those resources in your own AWS account when you deploy. The agent edits the service and runs it locally rather than calling AWS:
// expenses/expenses.ts
import { api } from "encore.dev/api";
import { SQLDatabase } from "encore.dev/storage/sqldb";
import { getAuthData } from "~encore/auth";
const db = new SQLDatabase("expenses", { migrations: "./migrations" });
export const approve = api(
{ expose: true, auth: true, method: "POST", path: "/expenses/:id/approve" },
async ({ id }: { id: number }): Promise<void> => {
const user = getAuthData()!;
await db.exec`
UPDATE expenses SET status = 'approved', approved_by = ${user.userID}
WHERE id = ${id} AND status = 'pending'`;
},
);
encore run starts Postgres locally and applies the migrations, so the agent can test the endpoint end to end with no cloud account at all. Since the database is part of the service code, the agent adds it in the same change as the endpoint and verifies both before anyone reviews them.
When the change is pushed, Encore connects to your AWS account through an IAM role you grant it, provisions RDS and the compute, and gives each service an IAM role limited to the resources it uses.
You can require manual infrastructure approval for an environment, so an Admin sees the new resources before they exist. Roles in Encore decide who can approve infrastructure and who can connect cloud accounts.
The agent keeps the same local power as the developer, while cloud access sits with Encore's IAM role, not the agent.
The agent can still read local secret values on the developer's machine, so keep production values on the production environment type. The IAM role you grant Encore needs permission to provision and manage infrastructure in that account, so the setup Encore suggests is a dedicated AWS account or sub-organization for it.
Run in your terminal to get started locally.
Move the deploy behind a reviewed path. On plain AWS that means a CI role assumed through OIDC that only runs after a merge. With Encore, the agent pushes code, and Encore provisions and deploys into your AWS account through its own IAM role. You can turn on manual infrastructure approval so an Admin approves new resources before they are created.
The agent works with whatever the developer can do locally, such as running the app and reading local development secrets. Cloud access sits with Encore's IAM role, not the agent, and production secrets are set per environment by someone with the right role.
The agent can run any API call the key allows, including ones you did not ask for, and the key can end up in its context, a log or a commit. OWASP lists this pattern as excessive agency in its top risks for LLM applications.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.