cannot
We cannot read your secrets, and with the split-account arrangement the identity we use cannot either.
No role we ask for includes secretmanager.versions.access.
Read this before you grant anything. It is the complete list of permissions we ask for, what each one is for, and the things we deliberately do not ask for. Nothing here is a summary of a longer list held somewhere else.
If you are handing this to a security reviewer, the four claims under Our safeguards are the ones they will want first.
the arrangement
You create one service account in your own project. You grant our deployer service account permission to impersonate it. We then act in your project as that service account, using tokens that expire in minutes.
No key, no password and no long-lived secret ever crosses between us. You wrote every permission on the list below, you can read every call we make in your own Cloud Audit Logs, and you can revoke us by removing one IAM binding without telling us first.
our deployer service account
agentmesh-deployer@langbench-1528148150979.iam.gserviceaccount.com
That is the only identity of ours named anywhere on this page, and the only one you ever grant anything to. It is an account we created for this and nothing else. It holds no role in our own project, so it cannot read our data either; its entire purpose is to be the principal your binding names.
It is deliberately not the service account our machines run as. That one is our project's default Compute Engine account, which everything on those machines shares, and a grant to it would be a grant to all of that. We refuse a grant on your Compute Engine default account for the same reason, further down this page, and it would be hard to say that with a straight face while asking you to accept ours. Our machines become this account first, then this account becomes yours.
read this first
These are not promises about our conduct. They are things the permissions on the list below do not allow, which your own IAM policy will confirm.
cannot
No role we ask for includes secretmanager.versions.access.
cannot
We ask for no logging role of any kind. Health comes from the job's own status and from a file the agent writes into its bucket. Your Cloud Audit Logs, including the record of everything we did, are not readable by us at all.
cannot
No role on the list includes setIamPolicy at project level. We cannot grant ourselves anything further, cannot add another principal, and cannot remove the binding you would use to revoke us.
cannot
Storage is two named buckets. Artifact Registry is one repository, read only. Cloud Run is the one job that runs your agent. There is no project-wide admin, no owner, no editor and no *.admin role anywhere on the list.
We also cannot:
setting it up
Replace YOUR_PROJECT with your project id throughout. Our deployer service account is the address above, and it is written out in full in the two commands that name it.
gcloud services enable \ run.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com \ secretmanager.googleapis.com \ storage.googleapis.com \ iamcredentials.googleapis.com \ cloudresourcemanager.googleapis.com \ --project=YOUR_PROJECT
You run this, not us. Enabling a service can change what your project is billed for, so it is not something a vendor should be able to do on your behalf. We deliberately do not ask for the role that would let us.
gcloud iam service-accounts create agentmesh-agent \ --display-name="AgentMesh deploy and runtime" \ --project=YOUR_PROJECT
That address is agentmesh-agent@YOUR_PROJECT.iam.gserviceaccount.com. The rest of this page calls it THEIR_SA.
It must be a service account you made. We refuse a grant on a Google managed account such as the Compute Engine default, because a grant on that account is a grant over everything else already running in your project, which is not what anybody means to agree to.
One repository for the container image, one bucket for the agent's own working files. You create both, so we never need permission to create anything at this level.
gcloud artifacts repositories create agentmesh \ --repository-format=docker --location=us-central1 --project=YOUR_PROJECT gcloud storage buckets create gs://YOUR_PROJECT-agentmesh \ --location=us-central1 --project=YOUR_PROJECT
The commands are in the next section, one block per permission, with the reason beside each.
gcloud iam service-accounts add-iam-policy-binding THEIR_SA \ --member="serviceAccount:agentmesh-deployer@langbench-1528148150979.iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountTokenCreator" \ --project=YOUR_PROJECT
This is the only binding that mentions us. Removing it is how you revoke us, and it takes effect within minutes because that is all the life a minted token has.
Then paste your project id and THEIR_SA into AgentMesh. We will impersonate the account and read your project's name and number. Until that read succeeds your grant stays marked "not verified" and we will not deploy anything into your project. We never mark a grant as working because somebody told us it was.
the list
Every role we ask for is in this table. Underneath it, one block per permission: the command, what the permission is for, and the stronger role we did not ask for instead.
| Role | Bound on | What it is for |
|---|---|---|
| roles/iam.serviceAccountTokenCreator | the one service account, held by our deployer | The grant that lets us act at all. It is the only binding that mentions us, and removing it is how you revoke us. |
| roles/run.developer | your project | Creates and updates the Cloud Run job or service that runs your agent, starts it, and reads its status back. |
| only if your policy strips it roles/browser |
your project | Reads project names and nothing else. Needed only if your organisation's policy strips resourcemanager.projects.get out of the role above. |
| roles/iam.serviceAccountUser | the one service account | Lets the identity deploying the workload run things as the identity the workload will use. |
| agentmeshSecretWriter, a custom role | your project | Creates a secret and adds a version to it. It cannot read a secret's value. |
| roles/secretmanager.secretAccessor | your project | The Cloud Run job reads the model API key at start. Read the block below before you grant this one. |
| roles/storage.objectAdmin | the one bucket | Reads and writes the objects in the agent's working bucket. |
| roles/storage.legacyBucketReader | the one bucket | Lets a tool confirm the bucket is there, which is all it does despite the name. |
| roles/artifactregistry.reader | the one repository | Cloud Run pulls your agent's image when the job starts. Read only. |
| only if we build in your project roles/cloudbuild.builds.editor |
your project | Submits a build and reads its result. It reaches nothing outside Cloud Build. |
| only if we build in your project roles/storage.objectAdmin roles/storage.legacyBucketReader |
the Cloud Build staging bucket | The bucket where the build's source is staged. |
roles/run.developer
gcloud projects add-iam-policy-binding YOUR_PROJECT \ --member="serviceAccount:THEIR_SA" --role="roles/run.developer"
Creates and updates the Cloud Run job or service that runs your agent, starts it, and reads its status back. This is the role that does the actual work.
not asked for: roles/run.admin
The difference between the two is the power to change who may call a service, including making it reachable by anyone on the internet. We do not need that and do not ask for it. If you want your agent to have a public address, that binding is yours to add.
This role also carries resourcemanager.projects.get, which is the harmless read our verification check uses. If your organisation's policy strips it, grant roles/browser as well: it reads project names and nothing else.
roles/iam.serviceAccountUser
gcloud iam service-accounts add-iam-policy-binding THEIR_SA \ --member="serviceAccount:THEIR_SA" \ --role="roles/iam.serviceAccountUser" --project=YOUR_PROJECT
Cloud Run refuses to create a workload unless the identity deploying it is allowed to run things as the identity the workload will use. Here those are the same account, so the binding names it twice. That is correct and not a typo.
This role is on the one service account, not on your project. It does not let that account impersonate any other account, and it does not include the permission to mint tokens.
projects/YOUR_PROJECT/roles/agentmeshSecretWriter
gcloud iam roles create agentmeshSecretWriter --project=YOUR_PROJECT \ --title="AgentMesh secret writer" --stage=GA \ --permissions=secretmanager.secrets.create,secretmanager.secrets.get,secretmanager.secrets.list,secretmanager.versions.add gcloud projects add-iam-policy-binding YOUR_PROJECT \ --member="serviceAccount:THEIR_SA" \ --role="projects/YOUR_PROJECT/roles/agentmeshSecretWriter"
Your agent needs a model API key. We put it into your Secret Manager and the Cloud Run job reads it from there at start, so the value is never written into the job's configuration where anybody with read access could see it.
not asked for: roles/secretmanager.admin
Google's predefined role for this is roles/secretmanager.admin, and it is the only predefined role that can create a secret. It also grants the power to read every secret value in the project and to change who else can. We are not asking for that. The four permissions above create a secret, add a new version to it, and nothing else.
The permission we are pointedly not asking for is secretmanager.versions.access, which is the one that reads a secret's value. Values go in and never come back out: our code has no call that reads one, and with this role it could not make one work.
roles/secretmanager.secretAccessor
gcloud projects add-iam-policy-binding YOUR_PROJECT \ --member="serviceAccount:THEIR_SA" --role="roles/secretmanager.secretAccessor"
the straight answer, not the reassurance
This one deserves a straight answer rather than a reassurance, because it appears to contradict the paragraph above.
The Cloud Run job has to read the key at start, and it runs as the same service account we deploy with. So that account does end up able to read secrets, even though nothing we run ever asks it to. On this arrangement the honest statement is: our code cannot read your secrets, and the identity it borrows can.
If that is not good enough for your review, the fix is two service accounts instead of one: agentmesh-agent for the deploy, holding everything above except this line, and a second account holding only this line which the job runs as. Tell us and we will set your deployment up that way. We have not made it the default because one account is one thing to audit, and the arrangement where a deployer can read the secrets it placed is the ordinary one.
Either way, put your agent in a project of its own. A project-level accessor binding reaches every secret in the project, and a project holding only this agent is a project where that sentence means very little.
roles/storage.objectAdmin and roles/storage.legacyBucketReader
gcloud storage buckets add-iam-policy-binding gs://YOUR_PROJECT-agentmesh \ --member="serviceAccount:THEIR_SA" --role="roles/storage.objectAdmin" gcloud storage buckets add-iam-policy-binding gs://YOUR_PROJECT-agentmesh \ --member="serviceAccount:THEIR_SA" --role="roles/storage.legacyBucketReader"
The agent's container is made fresh for every message, so anything meant to outlive one message lives in this bucket: the message going in, the answer coming out, and any files the work produces. The first role reads and writes the objects in it. The second one lets a tool confirm the bucket is there, which is all legacyBucketReader does despite the name.
not asked for: roles/storage.admin
Both roles are scoped to this one bucket. Not roles/storage.admin, which could delete the bucket and change who can read it, and not a project-level binding, which would reach every bucket you have.
roles/artifactregistry.reader
gcloud artifacts repositories add-iam-policy-binding agentmesh \ --location=us-central1 --project=YOUR_PROJECT \ --member="serviceAccount:THEIR_SA" --role="roles/artifactregistry.reader"
Cloud Run pulls your agent's image from this repository when the job starts. Read only, and on the one repository.
optional
You can skip this whole section. It applies when your agent is built from source rather than from an image that already exists, and the reason we offer it at all is that building in your project means your code, your build service and your bill, rather than ours.
gcloud projects add-iam-policy-binding YOUR_PROJECT \ --member="serviceAccount:THEIR_SA" --role="roles/cloudbuild.builds.editor" gcloud storage buckets create gs://YOUR_PROJECT_cloudbuild \ --location=us-central1 --project=YOUR_PROJECT gcloud storage buckets add-iam-policy-binding gs://YOUR_PROJECT_cloudbuild \ --member="serviceAccount:THEIR_SA" --role="roles/storage.objectAdmin" gcloud storage buckets add-iam-policy-binding gs://YOUR_PROJECT_cloudbuild \ --member="serviceAccount:THEIR_SA" --role="roles/storage.legacyBucketReader"
roles/cloudbuild.builds.editor submits a build and reads its result. It reaches nothing outside Cloud Build. The bucket is where the build's source is staged, and it is the name Cloud Build looks for by default.
One more binding is needed and it is not about us: your own Cloud Build service account has to be allowed to push the image it just built.
gcloud artifacts repositories add-iam-policy-binding agentmesh \ --location=us-central1 --project=YOUR_PROJECT \ --member="serviceAccount:$(gcloud projects describe YOUR_PROJECT --format='value(projectNumber)')-compute@developer.gserviceaccount.com" \ --role="roles/artifactregistry.writer"
turning us off
gcloud iam service-accounts remove-iam-policy-binding THEIR_SA \ --member="serviceAccount:agentmesh-deployer@langbench-1528148150979.iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountTokenCreator" --project=YOUR_PROJECT
You do not need to tell us, and you do not need our agreement. Within minutes every call we try to make fails. We record that as a revocation rather than as an error, we stop retrying, and we say so on your grant. We will not keep knocking.
What stays behind is whatever we already created: the Cloud Run job, the secrets, the bucket contents and the image. They are in your project, they are yours, and they are yours to delete. If you ask us to remove the deployment before you revoke, we tear down only what we created and tell you what is left.
checking us
Everything we do in your project is done as THEIR_SA, so your own audit log holds the complete list:
gcloud logging read \ 'protoPayload.authenticationInfo.principalEmail="THEIR_SA"' \ --project=YOUR_PROJECT --limit=100
We publish the same list from our side, without being asked, at the action log in your AgentMesh account. The two should agree call for call. If they ever do not, yours is the one to believe, and we would want to know.
the trade
Once your agent runs in your project, its availability is your project's availability. Your quota, your regions and your outages. We operate it, but we cannot speak for any of that, and our status page does not cover it.