Last reviewed: 2026-08-11

Direct answer

Keep model work and cloud deployment authority in different jobs. A coding agent can use CometAPI while it reads a repository, proposes a patch, and runs tests, but that job should have neither cloud deployment access nor permission to request a GitHub OIDC identity document. A separate deployment job should start only after the reviewed commit or artifact has crossed your approval boundary.

Grant id-token: write only to that deployment job. Configure the cloud provider to accept the GitHub issuer only when the expected audience, repository identity, workflow, branch or environment, and other supported claims match. The provider can then issue a short-lived cloud session for that job. GitHub’s OpenID Connect guide explains that this model avoids duplicating long-lived cloud credentials as repository secrets and that the resulting access is limited to the job’s lifetime.

This separation matters even when both stages belong to one automation. OIDC is the deployment identity plane; CometAPI access is the model-routing plane. Do not treat one as proof for the other, pass cloud access material into agent context, or add a static cloud credential when the exchange fails. A failed exchange should stop deployment and leave the tested artifact available for diagnosis.

Who this is for

This guide is for platform engineers and repository maintainers who let coding agents prepare changes in GitHub Actions and then promote reviewed artifacts to AWS, Google Cloud, or another provider that supports workload federation. It is also useful for teams moving away from a shared deployment secret that every workflow, tool, or agent step could potentially read.

You will get the most value if you can change workflow permissions, configure a provider trust policy, and define a protected deployment environment. If your current workflow combines agent execution, testing, approval, and deployment in one job, start by mapping those boundaries. The related guide on permission and secret boundaries for coding agents is a useful companion for that inventory.

Key takeaways

  • Give the agent job only the repository and test access it needs; keep cloud identity federation out of it.
  • Grant id-token: write at the deployment-job level, not as a broad workflow default.
  • Enforce issuer, audience, repository, ref, workflow, and environment conditions in the provider trust policy, outside the file the agent can edit.
  • Treat GitHub’s subject format as a contract to verify. Repositories created after July 15, 2026 use a newer immutable default subject format that includes owner and repository IDs.
  • Test both an allowed deployment and a deliberately denied claim combination before removing static cloud credentials.
  • Log claim-match metadata, artifact identity, and provider request identifiers, but never raw identity material, access values, or model-gateway secrets.

Sources checked

Contract details to verify

Define two identity planes

Write down the boundary before editing YAML. The agent/build stage may call the model gateway, inspect the checkout, run linters, and produce a candidate artifact. It must not be able to turn a model response into cloud deployment authority. The deployment stage consumes the reviewed artifact and uses a provider role or service identity whose trust policy is independent of the agent’s instructions.

StageAllowed identityExpected authorityExplicitly unavailable
Agent and buildCometAPI model access plus the repository and test tools needed for the taskRead, test, and produce a candidate changeCloud identity request, provider role, production deploy action
Review and promotion gateHuman or protected-environment decisionApprove the exact commit or artifactAutomatic permission expansion
DeploymentGitHub OIDC identity accepted by the providerDeploy the approved artifact with a narrow roleModel-context access to cloud credentials or unrestricted repository mutation

Keep the model-gateway configuration in the agent boundary and the cloud trust configuration in the provider or platform-admin boundary. An agent may propose a workflow change, but a reviewer should treat edits to permissions, triggers, environments, and trust policies as security-relevant changes. Do not let the agent decide that a denied exchange should use another credential source.

Pin the claim contract

List the claims your provider will check and record the expected source for each one:

  1. Issuer. Accept the GitHub OIDC issuer configured for your provider, with the exact case and spelling required by that provider.
  2. Audience. Use the audience expected by the provider’s federation action. An audience mismatch should fail closed rather than be silently rewritten.
  3. Repository identity. Restrict the organization and repository. Prefer immutable identifiers where the provider and current GitHub subject format support them.
  4. Execution scope. Restrict the branch, tag, deployment environment, or reusable-workflow reference that is allowed to assume the role.
  5. Optional repository properties. GitHub documents custom properties as OIDC claims for attribute-based access control. Use them only when the provider can map and enforce them, and govern who can set or change the property.

Do not copy an old sub condition into a new repository without checking the current token contract. GitHub’s refetched documentation notes that repositories created after July 15, 2026 use an immutable default subject format containing owner and repository IDs, while older repositories can retain the previous format. A policy that assumes the wrong shape should deny access, which is safer than broadening the condition to make the error disappear. Inspect the provider’s claim documentation and use a controlled diagnostic path; do not put a raw identity document in logs.

The provider examples differ. The AWS pattern scopes a role to a specific organization, repository, and branch and checks the audience. The Google Cloud pattern uses workload identity federation and attribute conditions. These are analogous controls, not interchangeable syntax.

Scope workflow permissions to the deploy job

A small permissions skeleton makes the boundary visible. The scripts below are placeholders for your reviewed build, federation, caller-check, and deployment commands; they intentionally contain no provider credential values.

name: reviewed-agent-deploy

permissions:
  contents: read

jobs:
  agent_build:
    permissions:
      contents: read
    steps:
      - name: Build and test proposed change
        run: ./ci/agent-build-and-test.sh

  deploy:
    needs: agent_build
    environment: production
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Obtain short-lived cloud access
        run: ./ci/federated-cloud-login.sh
      - name: Verify expected caller
        run: ./ci/verify-cloud-caller.sh
      - name: Deploy reviewed artifact
        run: ./ci/deploy-reviewed-artifact.sh

The federation wrapper should fail closed. It should request the job identity, perform the provider exchange, run a non-mutating caller check, compare the returned account, project, or role to the expected deployment target, and only then invoke the deploy command. It should not print the exchange input or output. The AWS walkthrough uses a caller-identity check and assigns id-token: write to the workflow job; use the same separation while adapting the action and policy to your provider.

Happy-path operator workflow

  1. The agent job receives the task and uses CometAPI for model work. It checks out the repository, runs tests, and writes a candidate artifact. No cloud identity permission is present in this job.
  2. The build records the commit identifier, artifact digest, test result, and workflow run metadata. It does not record model-gateway secrets or raw identity material.
  3. A reviewer or protected environment approves the exact commit or artifact. The deployment job cannot substitute a newly built artifact after approval.
  4. The deployment job starts with id-token: write. The provider validates the issuer, audience, repository, execution scope, and any configured environment or property condition.
  5. A successful exchange creates a short-lived cloud session. The caller-check step confirms that the session maps to the expected target and role before any mutating command runs.
  6. The job deploys the approved artifact, emits sanitized audit fields, and exits. GitHub describes the resulting provider access as available for the job and automatically expiring afterward.

The key observation is that the model call and the cloud exchange are adjacent steps in a pipeline, not one shared authority. A model response can suggest a deployment change, but only the independently enforced provider contract can grant deployment access.

Error-path operator workflow

Exercise the denial path in a non-production account before cutover. Start with an otherwise valid build, then use a test branch, environment, or workflow identity that the provider trust policy intentionally excludes.

  1. The agent build completes and produces the same kind of artifact as the happy path.
  2. The deploy job requests an identity, but the provider rejects the issuer, audience, subject, or attribute condition. The federation wrapper maps the result to a stable reason code such as claim_mismatch or audience_mismatch.
  3. The wrapper exits before the caller check can run a mutating command. There is no automatic fallback to a static cloud secret.
  4. The log records the workflow, repository identifiers, environment, policy version, reason code, and run identifier, with no raw identity or access material.
  5. The operator compares the expected claim contract with the provider policy and the current GitHub subject format. Any policy change goes through review, then the deny test is repeated.

Also test the opposite failure: an allowed identity pointed at the wrong deployment target. A successful federation exchange is not enough; the caller-check must reject an unexpected account, project, role, or environment before deployment.

Sanitize the operator log

Keep enough metadata to correlate a run without turning logs into a credential store. A representative event can look like this:

{
  "event_type": "cloud_identity_exchange",
  "workflow_name": "reviewed-agent-deploy",
  "repository_id": "74",
  "repository_owner_id": "65",
  "run_id": "example-run",
  "run_attempt": 2,
  "job_name": "deploy",
  "environment": "production",
  "git_ref": "refs/heads/main",
  "commit_sha": "example-commit",
  "provider": "cloud-provider",
  "requested_role": "deploy-role",
  "claim_policy_version": "v3",
  "claim_match_result": "allowed",
  "deny_reason_code": null,
  "deployment_artifact_digest": "example-digest",
  "result": "success"
}

Do not log a raw OIDC document, the resulting cloud access value, request headers, environment dumps, or the CometAPI access configuration. If a diagnostic field might contain one of those values and your logger cannot omit it, replace the whole field with [REDACTED]. Keep the event schema stable so a denied exchange is as searchable as a successful one.

Roll out and roll back deliberately

Inventory existing cloud secrets without printing their values. Create the provider trust relationship in a non-production target, run an allowed deployment and several denied combinations, and verify that the logs contain only the fields you intended. Then move the same contract to production and remove the static cloud credential from the deployment job.

A rollback should stop promotion or disable the federation trust while the policy is investigated. It should not hand the agent a backup cloud secret. If an emergency process must exist, isolate it behind a separately approved, human-operated procedure rather than a branch the coding agent can select.

Failure modes

  • The permission is granted at workflow scope. A future agent step inherits id-token: write, so a harmless build change can request an identity. Keep the permission on the smallest deploy job.
  • The trust condition is wider than the workflow. Wildcard repositories, branches, or environments turn a successful exchange into an unintended deployment path. Start with one repository and one protected target.
  • The subject format is copied from an old example. GitHub’s current documentation calls out the post-July 15, 2026 immutable subject format for newly created repositories. Verify the actual contract instead of weakening the condition.
  • The audience is wrong. The provider rejects the exchange even though the repository and branch look correct. Treat this as a configuration error and do not rewrite the audience in the workflow to chase a pass.
  • A custom property is missing or stale. A repository property can be unset, renamed, or changed without the provider policy being updated. Make property ownership and change review explicit.
  • A static fallback remains reachable. The login wrapper catches a federation error and retries with a shared secret. Remove that branch; a denial should be observable and actionable.
  • The artifact changes between review and deploy. Rebuilding in the deploy job can publish code the reviewer did not approve. Bind deployment to the recorded commit or artifact digest.
  • Logs leak identity material. Debug output from a provider action or shell command can expose more than the event schema permits. Disable verbose dumps and test the log redaction path.
  • The role has excessive permissions. OIDC limits who can assume a role, not what that role can do. Attach only the actions and resources required for the deployment.
  • Provider examples are mixed together. AWS trust conditions and Google attribute mappings use different policy languages. Keep one provider’s contract in its own reviewed configuration and link the provider’s current reference from the runbook.

FAQ

Does id-token: write give the job cloud access by itself?

No. It permits the job to request a GitHub identity document. The cloud provider must validate the issuer, audience, and trust conditions before issuing a short-lived cloud session. The provider role’s permissions still determine what that session can do.

Should the agent and deployment use the same job for fewer steps?

No. Combining them makes the model-running step adjacent to deployment authority and makes it difficult to prove which change earned access. Separate jobs create a clear permission boundary, let the review gate sit between them, and make a denied exchange safe to retry without rerunning model work.

Can OIDC replace the configuration used to reach CometAPI?

The supplied sources document OIDC for GitHub Actions and cloud-provider federation; they do not establish any CometAPI authentication feature. Keep CometAPI model access as a separate, narrowly scoped configuration in the agent job. The point of this pattern is that a model call does not become cloud authority.

Are the AWS and Google Cloud examples interchangeable?

No. AWS’s example uses an IAM OIDC provider and a trust policy with repository and branch conditions. Google Cloud’s guide uses Workload Identity Federation with attribute mappings and conditions. The shared design is claim-restricted, short-lived access; the issuer setup, audience, policy language, and login action must follow the provider you actually use.

Do I need repository custom properties?

No. They are an optional way to express attributes such as an environment tier or data classification. GitHub documents how administrators can include selected properties as OIDC claims. Use them only when the cloud provider can enforce the mapped claim and when property changes receive the same review as trust-policy changes.

How do I know the rollout is safe?

Prove both directions. An approved repository and environment must exchange successfully and deploy only the recorded artifact. An excluded branch, repository, audience, or environment must be denied before any mutating command. Inspect the sanitized event fields and the provider audit trail, then remove the static cloud secret only after both tests are repeatable.

What should happen when the provider is unavailable?

The deployment should stop. Preserve the build result and a reason code, alert the operator through your normal channel, and retry only after the provider or policy issue is understood. Do not route the request through a broader role or expose a backup credential to the agent.

Reader next step

Open the workflow and its provider trust policy side by side. Mark which job can call the model gateway, which job can request an OIDC identity, which human or environment gate approves promotion, and which exact artifact is deployed. Then:

  1. Move id-token: write to the deployment job only.
  2. Encode issuer, audience, repository, ref or environment, and role conditions in the provider policy.
  3. Add a caller check and a sanitized event schema.
  4. Run one allowed and one deliberately denied deployment in a non-production target.
  5. Review the workflow permissions with the CI permission checklist and the deployment plan with the Terraform plan review guide .
  6. Remove the static cloud credential from the deployment path once the tests pass.

After the cloud boundary is explicit, Start with CometAPI for the model-routing side of the workflow while keeping deployment identity in its own reviewed job.