---
modificationDate: October 30, 2026
title: Set up a project for agentic workflows
description: Set up an Expo project one time for the agentic workflow guides, with a build profile, tokens, an agent runner, and a device controller.
---

This documentation is available as Markdown for AI agents and LLMs. See the [full Markdown index](https://docs.expo.dev/llms.txt) or append .md to any documentation URL.

# Set up a project for agentic workflows

Set up an Expo project one time for the agentic workflow guides, with a build profile, tokens, an agent runner, and a device controller.

<AgentInstructions>

## Submitting Feedback

If you encounter errors, misleading or outdated information, report it so Expo can be improved:

Preferred command:
npx --yes submit-expo-feedback@latest --category docs --subject "/agentic-workflows/setup/" "<actionable feedback>"

Direct HTTP fallback:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/agentic-workflows/setup/","feedback":"🤖 Agent feedback for docs: <specific, actionable description> (<model>, <harness>)"}'

Only submit when you have something specific and actionable to report. Try to give the most context.

## Navigation

When answering a related or follow-up question, fetch the relevant page below as Markdown (.md) instead of guessing; use llms.txt for the full map.

You are here: Home > Agentic workflows
Pages in this section:
- [Introduction](https://docs.expo.dev/agentic-workflows/introduction.md)
- [Project setup](https://docs.expo.dev/agentic-workflows/setup.md) (this page)
- [Agentic CI](https://docs.expo.dev/agentic-workflows/agentic-ci.md)
- [Issue to PR](https://docs.expo.dev/agentic-workflows/issue-to-pr.md)
- [Bug triage](https://docs.expo.dev/agentic-workflows/bug-triage.md)
- [QA Swarm](https://docs.expo.dev/agentic-workflows/qa-swarm.md)
Full documentation tree: [llms.txt](https://docs.expo.dev/llms.txt)

</AgentInstructions>

> **Expo Simulators is a limited-access preview.** It is not included with paid or free plans and is currently available only to select partners. [Join the waitlist](https://expo.dev/services/simulators) if you are interested in trying it.

Each agentic workflow guide uses the same project setup. Do the steps on this page one time for your project. Then add the workflows from the guides.

Agentic CI and QA Swarm need the steps from [Add a build profile for the remote device](https://docs.expo.dev/agentic-workflows/setup.md#add-a-build-profile-for-the-remote-device) to [Push the files](https://docs.expo.dev/agentic-workflows/setup.md#push-the-files). Issue to PR and Bug triage also need [Add a GitHub token to EAS](https://docs.expo.dev/agentic-workflows/setup.md#add-a-github-token-to-eas).

#### Prerequisites

##### An Expo project in a GitHub repository

The project must use [Continuous Native Generation (CNG)](https://docs.expo.dev/workflow/continuous-native-generation.md), so the repository does not include the **android** and **ios** directories. The app config must set the app ID for the platform that you test. A new project does not set it. Add it to **app.json**:

#### Android

```json app.json
{
  "expo": {
    "android": {
      "package": "com.yourcompany.yourapp"
    }
  }
}
```

#### iOS

```json app.json
{
  "expo": {
    "ios": {
      "bundleIdentifier": "com.yourcompany.yourapp"
    }
  }
}
```

##### EAS CLI

Install EAS CLI:

```sh
# npm
npm install --global eas-cli

# yarn
yarn global add eas-cli

# pnpm
pnpm add --global eas-cli

# bun
bun add --global eas-cli
```

##### GitHub CLI

Issue to PR and Bug triage use [GitHub CLI](https://cli.github.com/) to add a repository secret, a label, and an issue. Install it, then sign in:

```sh
gh auth login
```

##### Expo Simulators access

The account that owns the project needs Expo Simulators access. In your project directory, link the project to EAS and check the access:

```sh
eas login
eas init
eas simulator:availability --json
```

An account with access returns `"available": true`. If the value is `false`, [join the waitlist](https://expo.dev/services/simulators) to request access.

##### A coding agent that can run in CI

The workflows run the agent from the command line, without a person. You can use any coding agent that has this mode and a key that works without a browser login. [Add the agent runner](https://docs.expo.dev/agentic-workflows/setup.md#add-the-agent-runner) has a ready-made runner for Claude Code, Codex, Cursor, and Grok. Create the key for your agent:

| Agent | How to get the key |
| --- | --- |
| Claude Code | Run `claude setup-token`. The token requires a Pro, Max, Team, or Enterprise plan. An Anthropic API key also works. |
| Codex | Create an OpenAI API key. The Codex docs recommend an API key for CI jobs. |
| Cursor | In the Cursor dashboard, open **API Keys**. |
| Grok | Create an xAI API key on [console.x.ai](https://console.x.ai). |

## Add a build profile for the remote device

The workflows install a build from the `preview` profile on each session. Merge these keys into the `preview` profile in **eas.json**, or add the profile if it does not exist:

#### Android

An Android Emulator session runs an APK:

```json eas.json
{
  "build": {
    "preview": {
      "distribution": "internal",
      "environment": "preview",
      "android": {
        "buildType": "apk"
      }
    }
  }
}
```

EAS signs the APK with an Android keystore. If the project has no Android keystore yet, create one before the first run. Run this command, select the `preview` profile, and let EAS generate a new keystore:

```sh
eas credentials --platform android
```

#### iOS

An iOS Simulator session runs a simulator build. A simulator build is not signed, so it needs no credentials:

```json eas.json
{
  "build": {
    "preview": {
      "distribution": "internal",
      "environment": "preview",
      "ios": {
        "simulator": true
      }
    }
  }
}
```

To test both platforms, add the `android` and the `ios` keys to the same profile. The fingerprint job in each workflow uses the same `preview` environment, so the fingerprints match the builds.

If your `preview` profile already makes builds for physical devices, `ios.simulator: true` stops those builds. In that case, add a separate profile for the agent, such as `agent`. Then change `profile: preview` to the name of that profile in each workflow file.

## Connect GitHub to the EAS project

The workflows start on GitHub events and post comments on PRs. Connect your GitHub repository to the EAS project. See [Automate workflows with GitHub events](https://docs.expo.dev/eas/workflows/get-started.md#automate-workflows-with-github-events).

If the app is in a subdirectory of the repository, such as **apps/my-app**, set the **Base directory** to that path. See [Configure your repository settings](https://docs.expo.dev/build/building-from-github.md#configure-your-repository-settings) and [Use a monorepo](https://docs.expo.dev/agentic-workflows/setup.md#use-a-monorepo).

## Create a robot token

The jobs start sessions with the access token of a [robot user](https://docs.expo.dev/accounts/programmatic-access.md#robot-users-and-access-tokens). A robot user cannot sign in to Expo, and it can do only what its role allows.

In the account that owns the project, open [**Access tokens**](https://expo.dev/accounts/%5Baccount%5D/settings/access-tokens). Under **Robot users**, create a robot user with the [Developer role](https://docs.expo.dev/accounts/account-types.md#manage-access). The Developer role is the lowest role that can start and stop sessions. Then create a token for the robot user. See [What the agent can do](https://docs.expo.dev/agentic-workflows/setup.md#what-the-agent-can-do) for more information.

Keep this token and the key of your agent out of files, logs, and chat.

## Add the tokens to EAS

In the project dashboard, open **Project settings** > [**Environment variables**](https://expo.dev/accounts/%5Baccount%5D/projects/%5Bproject%5D/environment-variables). Select **Add Variables**. Add these variables with the **Secret** visibility:

| Name | Value |
| --- | --- |
| `EXPO_TOKEN_SIMULATOR` | The robot token |
| `CLAUDE_CODE_OAUTH_TOKEN`, `ANTHROPIC_API_KEY`, `CODEX_API_KEY`, `CURSOR_API_KEY`, or `XAI_API_KEY` | The key of your agent |

Add the variables to the **preview** environment. The workflows use **preview** for the builds and for the agent, and the agent can read each variable of that environment. So keep no other secrets in **preview**. Values that are not secret, such as `EXPO_PUBLIC_` variables, can stay, because they are in the app already. If **preview** must have another secret, such as an `NPM_TOKEN` for private packages, the agent can read that secret too.

If **preview** has a `SENTRY_AUTH_TOKEN`, remove it from **preview**, and add `SENTRY_DISABLE_AUTO_UPLOAD` with the value `true`. Then the builds do not upload source maps or debug files to Sentry.

On the Enterprise and Production plans, you can [create a custom environment](https://docs.expo.dev/eas/environment-variables/manage.md#custom-environments) for the agent. Then change `environment: preview` to the name of that environment in the build profile and in each workflow file.

Check that the list has the variables:

```sh
eas env:list --environment preview
```

## Add the agent runner

This file runs your agent without a person. Use the version for your agent. The jobs run it as `bash .eas/agents/run-agent.sh <prompt-file> <mode>`. The mode is `device` when the agent tests the app, and `change` when the agent changes the code. For another agent, write a runner that takes the same two arguments and runs the agent without a person.

#### Claude Code

```sh .eas/agents/run-agent.sh
#!/usr/bin/env bash
set -euo pipefail

case "$2" in
  device) tools='Read,Glob,Grep,Write,Bash(npx --yes eas-cli@latest simulator:exec npx --yes agent-device@latest *),Bash(npx --yes -p @swmansion/argent@latest argent *)' ;;
  change) tools='Read,Glob,Grep,Edit,Write,Bash(npx tsc --noEmit)' ;;
  *)
    echo "Unknown mode \"$2\". Use device or change." >&2
    exit 1
    ;;
esac

mkdir -p agent-output/evidence
npx --yes @anthropic-ai/claude-code@latest -p "Do the task that standard input describes." \
  --allowedTools "$tools" --permission-mode dontAsk --max-turns 80 \
  --output-format stream-json --verbose < "$1" > agent-output/evidence/agent-log.jsonl || {
  tail -n 1 agent-output/evidence/agent-log.jsonl >&2
  exit 1
}
```

#### Codex

```sh .eas/agents/run-agent.sh
#!/usr/bin/env bash
set -euo pipefail

exec npx --yes @openai/codex@latest exec \
  --sandbox danger-full-access \
  --skip-git-repo-check \
  - < "$1"
```

#### Cursor

```sh .eas/agents/run-agent.sh
#!/usr/bin/env bash
set -euo pipefail

if ! command -v agent > /dev/null 2>&1; then
  curl https://cursor.com/install -fsS | bash
  export PATH="$HOME/.local/bin:$PATH"
fi

exec agent -p --force --trust --output-format text "Read the file $1 and do the task that it describes."
```

Cursor also reads permissions from **.cursor/cli.json**. Add this file to the root of your project:

```json .cursor/cli.json
{
  "permissions": {
    "allow": ["Read(**/*)", "Write(**/*)", "Shell(npx)"],
    "deny": [
      "Shell(curl)",
      "Shell(wget)",
      "Shell(git)",
      "Shell(gh)",
      "Shell(rm)",
      "Write(.eas/**)",
      "Write(.github/**)"
    ]
  }
}
```

#### Grok

```sh .eas/agents/run-agent.sh
#!/usr/bin/env bash
set -euo pipefail

case "$2" in
  device) allow=(--allow 'Write(agent-output/**)' --allow 'Bash(npx --yes eas-cli@latest simulator:exec npx --yes agent-device@latest *)' --allow 'Bash(npx --yes -p @swmansion/argent@latest argent *)') ;;
  change) allow=(--allow 'Edit(./**)' --allow 'Bash(npx tsc --noEmit)') ;;
  *)
    echo "Unknown mode \"$2\". Use device or change." >&2
    exit 1
    ;;
esac

if ! command -v grok > /dev/null 2>&1; then
  curl -fsSL https://x.ai/cli/install.sh | bash
  export PATH="$HOME/.grok/bin:$PATH"
fi

exec grok --prompt-file "$1" "${allow[@]}" --disable-web-search --max-turns 80
```

The `change` mode allows only `npx tsc --noEmit`, so the agent cannot run the tests or the linter of your project. To allow them, add their commands to the `change` mode. For example, add `Bash(bun run test)` to the Claude Code runner, or `--allow 'Bash(bun run test)'` to the Grok runner.

## Add the device controller

The agent controls the remote device with a controller: [agent-device](https://docs.expo.dev/agents/agent-device.md) or [Argent](https://docs.expo.dev/agents/argent.md). This script starts an Expo Simulators session for the controller. Then it writes the device details and the commands of the controller to **agent-output/device.md**, and the job adds this file to the prompt of the agent. Use the version for your controller.

The jobs run the script as `source .eas/agents/start-session.sh <platform> <build ID> <session name> <tag>`. The `source` command runs the script in the shell of the job, so the job keeps the session details and stops the session when it ends. The script reads the app ID with `npx expo config`, so the app ID can come from **app.json**, **app.config.js**, or **app.config.ts**.

#### agent-device

```sh .eas/agents/start-session.sh
#!/usr/bin/env bash

case "$1" in
  android) APP_ID_KEY=package ;;
  ios) APP_ID_KEY=bundleIdentifier ;;
  *)
    echo "Unknown platform \"$1\". Use android or ios." >&2
    exit 1
    ;;
esac
APP_ID=$(npx expo config --json | node -e 'const config = JSON.parse(require("fs").readFileSync(0, "utf8")); console.log(config[process.argv[1]]?.[process.argv[2]] ?? "")' "$1" "$APP_ID_KEY")
: "${APP_ID:?The app config has no app ID for $1. Add it to app.json or app.config.js.}"
mkdir -p agent-output/evidence

export EXPO_TOKEN="$EXPO_TOKEN_SIMULATOR"
npx --yes eas-cli@latest simulator:start --platform "$1" --type agent-device \
  --build-id "$2" --name "$3" --tag "$4" \
  --max-duration-minutes 30 --json > /tmp/session.json
trap 'npx --yes eas-cli@latest simulator:stop --non-interactive > /dev/null 2>&1 || true' EXIT

npx --yes eas-cli@latest simulator:exec npx --yes agent-device@latest open "$APP_ID" --platform "$1" > /dev/null

cat > agent-output/device.md << EOF
## Device

- Platform: $1
- App ID: $APP_ID

Control the device only with this shell command:

    npx --yes eas-cli@latest simulator:exec npx --yes agent-device@latest <command>

Run each command alone. Do not join commands with ;, &&, or |. The folder agent-output/evidence already exists. If a command is denied, run it again alone one time before you stop. Write files, such as the verdict, with your file tools, not with shell commands.

Use these agent-device commands:

- snapshot -i lists the elements on the screen, with references such as @e2. The references change on each screen, so run snapshot -i again after each action.
- snapshot without -i also lists the plain text on the screen.
- press @e2 taps an element.
- fill @e4 "text" types text into a field.
- keyboard enter presses the Enter key of the keyboard.
- scroll down scrolls the screen.
- screenshot agent-output/evidence/<number>-<name>.png saves a screenshot.
- open $APP_ID --platform $1 opens the app again.
EOF

if [ -f .eas/agents/app-facts.md ]; then
  printf '\n## App facts\n\n' >> agent-output/device.md
  cat .eas/agents/app-facts.md >> agent-output/device.md
fi
```

#### Argent

```sh .eas/agents/start-session.sh
#!/usr/bin/env bash

case "$1" in
  android) APP_ID_KEY=package; SCALE=0.9 ;;
  ios) APP_ID_KEY=bundleIdentifier; SCALE=1 ;;
  *)
    echo "Unknown platform \"$1\". Use android or ios." >&2
    exit 1
    ;;
esac
APP_ID=$(npx expo config --json | node -e 'const config = JSON.parse(require("fs").readFileSync(0, "utf8")); console.log(config[process.argv[1]]?.[process.argv[2]] ?? "")' "$1" "$APP_ID_KEY")
: "${APP_ID:?The app config has no app ID for $1. Add it to app.json or app.config.js.}"
mkdir -p agent-output/evidence

export EXPO_TOKEN="$EXPO_TOKEN_SIMULATOR"
npx --yes eas-cli@latest simulator:start --platform "$1" --type argent \
  --build-id "$2" --name "$3" --tag "$4" \
  --max-duration-minutes 30 --json > /tmp/session.json
trap 'npx --yes eas-cli@latest simulator:stop --non-interactive > /dev/null 2>&1 || true' EXIT

set -a
source ./.env.eas-simulator
set +a

UDID=""
for attempt in 1 2 3 4; do
  UDID=$(npx --yes -p @swmansion/argent@latest argent run list-devices 2> /dev/null \
    | grep -oE '"(udid|serial)" *: *"[^"]+"' | head -n 1 | sed -E 's/.*"([^"]+)"$/\1/' || true)
  [ -n "$UDID" ] && break
  sleep 15
done
: "${UDID:?Argent did not list a device. See the logs of this job.}"

cat > agent-output/device.md << EOF
## Device

- Platform: $1
- App ID: $APP_ID
- Device ID: $UDID

Control the device only with this shell command:

    npx --yes -p @swmansion/argent@latest argent run <tool> --udid $UDID <options>

Run each command alone. Do not join commands with ;, &&, or |. The folder agent-output/evidence already exists. If a command is denied, run it again alone one time before you stop. Write files, such as the verdict, with your file tools, not with shell commands.

Use these Argent tools:

- describe lists the elements on the screen. Each element has a frame in coordinates from 0 to 1.
- gesture-tap --x <x> --y <y> taps a point. Use the center of the frame of an element from describe. Never use pixels. Run describe again after each change on the screen.
- keyboard --text "text" types text into the field that has focus.
- gesture-swipe --fromX 0.5 --fromY 0.7 --toX 0.5 --toY 0.3 scrolls the screen down.
- screenshot --scale $SCALE --out agent-output/evidence/<number>-<name>.png saves a screenshot.
- restart-app --bundleId $APP_ID opens the app again.
EOF

if [ -f .eas/agents/app-facts.md ]; then
  printf '\n## App facts\n\n' >> agent-output/device.md
  cat .eas/agents/app-facts.md >> agent-output/device.md
fi
```

The Argent version reads the session details from **.env.eas-simulator**, so the agent can reach the device. Then it waits until Argent lists the device. An Android Emulator can take a few minutes to start. Android screenshots use a scale of 0.9, because a scale of 1 can fail on an Android Emulator.

The Claude Code and Grok runners allow only the commands of each mode. Their `device` mode must allow the Argent CLI, as the runners in [Add the agent runner](https://docs.expo.dev/agentic-workflows/setup.md#add-the-agent-runner) do. A runner that allows only agent-device denies each Argent command. If your **run-agent.sh** does not have the `argent` rule, replace it with the version in [Add the agent runner](https://docs.expo.dev/agentic-workflows/setup.md#add-the-agent-runner).

Each session starts on a new install of the app. If the agent needs facts about your app, add them to **.eas/agents/app-facts.md**. The script adds this file to **agent-output/device.md**, so each workflow gives the facts to the agent. For example, write how to pass the onboarding screens, the text of each main screen on each platform, and what the agent must not touch:

```md .eas/agents/app-facts.md
- The app opens on two onboarding screens. Select Next on each screen to reach the main screen.
- The title of the main screen is "Tasks" on iOS and "My App" on Android.
- Do not sign out, and do not delete the account.
```

## Push the files

The sessions and the jobs write files to your project directory. The **.env.eas-simulator** file has a token for the session. Add these lines to **.gitignore**:

```sh .gitignore
.env.eas-simulator
agent-output/
```

Then push the files:

```sh
git add .gitignore eas.json .eas/agents/run-agent.sh .eas/agents/start-session.sh
git commit -m "Add the agent runner and the device controller"
git push
```

If you changed **app.json**, also add it. If you use Cursor, also add **.cursor/cli.json**. If you added app facts, also add **.eas/agents/app-facts.md**.

## Add a GitHub token to EAS

Issue to PR and Bug triage need this step. Issue to PR pushes a branch, opens a PR, and adds comments to the issue. Bug triage creates issues for TestFlight feedback and posts its verdict on the issue. QA Swarm needs this step only to post its report on a PR. These tasks need a GitHub token.

On GitHub, create a [fine-grained personal access token](https://github.com/settings/personal-access-tokens/new). Under **Repository access**, select only your repository. Give it these permissions:

-   **Contents:** Read and write
-   **Issues:** Read and write
-   **Pull requests:** Read and write

In the project dashboard, open **Project settings** > [**Environment variables**](https://expo.dev/accounts/%5Baccount%5D/projects/%5Bproject%5D/environment-variables). Add these variables to the **preview** environment:

| Name | Value | Visibility |
| --- | --- | --- |
| `GITHUB_TOKEN` | The GitHub token | Secret |
| `GITHUB_REPOSITORY` | The owner and the name of the repository, such as `acme/app` | Plain text |

The job removes the GitHub token from the environment of the agent. An agent that can run shell commands can still read the variables of the job. So give the token access only to this repository. See [What the agent can do](https://docs.expo.dev/agentic-workflows/setup.md#what-the-agent-can-do) for more information.

GitHub shows the owner of the token as the author of each PR that Issue to PR opens. GitHub does not let an author approve their own PR. If your repository requires a review, another person must approve these PRs. To keep your own approval, create the token with a separate GitHub account for the agent.

## Test the setup by hand

Before you add a workflow, you can test the build and the controller from your computer. This test uses agent-device on iOS.

Create a build with the profile from [Add a build profile for the remote device](https://docs.expo.dev/agentic-workflows/setup.md#add-a-build-profile-for-the-remote-device):

```sh
eas build --platform ios --profile preview
```

Then run these commands in your project directory. The `simulator:start` command fails outside a project directory. Replace `<build ID>` with the ID of the build, and `<app ID>` with the `ios.bundleIdentifier` of your app:

```sh
eas simulator:start --platform ios --build-id <build ID>
eas simulator:exec npx --yes agent-device@latest open <app ID> --platform ios
eas simulator:exec npx --yes agent-device@latest snapshot -i
eas simulator:stop
```

The `simulator:start` command writes the session details to **.env.eas-simulator**. The `simulator:exec` command reads this file, so it does not need an Expo login. The `snapshot -i` command lists the elements on the screen, such as buttons and text. If the list shows your app, the build and the controller work.

## Use a monorepo

The guides show each file at the root of the app. In a monorepo, the app is in a subdirectory of the repository, such as **apps/my-app**. The jobs run in that directory, so most files work without a change. Make these changes:

-   Put **.eas** and the other files of the guides in the app directory, such as **apps/my-app/.eas/agents/run-agent.sh**. Put the GitHub Action of Issue to PR in **.github/workflows** at the root of the repository.
    
-   The `eas/upload_artifact` step reads `path` from the root of the repository. In each of these steps, put the app directory in front of the path. For example, use `apps/my-app/agent-output/evidence/**/*`. In Issue to PR, use `/tmp/agent-change/apps/my-app/agent-output/**/*`.
    
-   The GitHub Action of Issue to PR runs its commands at the root of the repository. Run them in the app directory:
    
    ```yaml .github/workflows/agent-label.yml
    jobs:
      start:
        defaults:
          run:
            working-directory: apps/my-app
    ```
    

The job script of Issue to PR finds the root of the repository and the app directory with Git, so it needs no change.

## What the agent can do

The agent reads text from PRs, issues, and TestFlight feedback. Another person can write instructions for the agent in that text. These workflows limit what the agent can do:

-   The agent can read each variable of the environment that the job uses, and the session file **.env.eas-simulator**. This file has a token for the current session. Keep no other secrets in that environment. See [Add the tokens to EAS](https://docs.expo.dev/agentic-workflows/setup.md#add-the-tokens-to-eas).
-   EAS does not start `pull_request` workflows for PRs from forks.

Each agent also has its own limits:

| Agent | Limit in these workflows |
| --- | --- |
| Claude Code | `--allowedTools` allows the file tools and the commands of one mode. The `device` mode allows agent-device through `eas simulator:exec`, and the Argent CLI. The `change` mode allows `npx tsc --noEmit`. |
| Codex | The runner does not read the mode, so the `device` and the `change` jobs give the agent the same rights. The agent can run any command on the EAS worker. Each job runs on its own worker. |
| Cursor | The runner does not read the mode, so the `device` and the `change` jobs give the agent the same rights. The agent can run each command that **.cursor/cli.json** does not deny. The file allows `Shell(npx)`, and `npx` can run any npm package. So the deny list is a weak limit. |
| Grok | `--allow` allows file changes and the commands of one mode. The `device` mode allows agent-device through `eas simulator:exec`, and the Argent CLI. The `change` mode allows `npx tsc --noEmit`. Grok also runs its read-only commands, such as `ls` and `cat`. It does not run other commands. |
| Other agent | The limits depend on the permission settings of its command-line tool. |

The code of a branch also runs in some workflows. In Agentic CI, the `check` job checks out the PR. In QA Swarm, each lane checks out the branch of `--ref`. So the code of that branch can change **.eas/agents/run-agent.sh** and the workflow files, and read `EXPO_TOKEN_SIMULATOR` and the key of your agent. It can also read `GITHUB_TOKEN` if you did [Add a GitHub token to EAS](https://docs.expo.dev/agentic-workflows/setup.md#add-a-github-token-to-eas). Each person who can push a branch to the repository can add such code.

So use a robot token with the Developer role, not your personal access token. A PR that reads the robot token can do only what the Developer role allows.
