This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Set up a project for agentic workflows
Edit page
Set up an Expo project one time for the agentic workflow guides, with a build profile, tokens, an agent runner, and a device controller.
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 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 to Push the files. Issue to PR and Bug triage also need Add a GitHub token to EAS.
5 requirements
5 requirements
1.
The project must use Continuous Native Generation (CNG), 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:
2.
Install EAS CLI:
3.
Issue to PR and Bug triage use GitHub CLI to add a repository secret, a label, and an issue. Install it, then sign in:
4.
The account that owns the project needs Expo Simulators access. In your project directory, link the project to EAS and check the access:
An account with access returns "available": true. If the value is false, join the
waitlist to request access.
5.
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 has a ready-made runner for Claude Code, Codex, Cursor, and Grok. Create the key for your agent:
1
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:
An Android Emulator session runs an 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:
An iOS Simulator session runs a simulator build. A simulator build is not signed, so it needs no credentials:
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.
2
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.
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 and Use a monorepo.
3
Create a robot token
The jobs start sessions with the access token of a robot user. 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. Under Robot users, create a robot user with the Developer role. 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 for more information.
Keep this token and the key of your agent out of files, logs, and chat.
4
Add the tokens to EAS
In the project dashboard, open Project settings > Environment variables. Select Add Variables. Add these variables with the Secret visibility:
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 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:
5
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.
Cursor also reads permissions from .cursor/cli.json. Add this file to the root of your project:
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.
6
Add the device controller
The agent controls the remote device with a controller: agent-device or Argent. 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.
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 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.
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:
7
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:
Then push the files:
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.
8
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. 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. Add these variables to the preview environment:
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 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:
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:
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_artifactstep readspathfrom the root of the repository. In each of these steps, put the app directory in front of the path. For example, useapps/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:
.github/workflows/agent-label.yml
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.
- EAS does not start
pull_requestworkflows for PRs from forks.
Each agent also has its own limits:
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. 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.