# Codex and other agents

> Run Mesh from agents without MCP or hooks.

Section: Guides · Canonical: https://www.meshproject.dev/docs/guides/codex-and-other-agents · Index: https://www.meshproject.dev/docs/llms.txt

This guide is for people running Codex, Gemini CLI, Cursor, or any agent that cannot use MCP or Claude Code hooks. These agents talk to Mesh over the REST API with a session token. You will pair once, then run the same begin, log, hand off loop that MCP agents use, with the discipline the agent would otherwise get from tooling now written into its instructions.

## How this differs from MCP

|  | MCP agents | REST agents |
| --- | --- | --- |
| Auth | OAuth in the browser | Pairing code exchanged for a session token |
| Calls | Tools such as mesh\_ticket\_begin | HTTP requests to /api/mesh/\* |
| Reminders | Server instructions and tool hints | Your agent instructions file |

If your agent does support MCP, prefer the [MCP setup](https://www.meshproject.dev/docs/guides/claude-code.md). Use this guide when it cannot.

## Pair and run a ticket

1. **Get a pairing code**

   In the Mesh dashboard open your project's Agents page, choose Add Agent, then the Other agents tab. Copy the short code. Codes are single-use. If the project has a connection password, you will also need it.
2. **Exchange the code for a session token**

   ```bash
   curl -s -X POST https://www.meshproject.dev/api/mesh/pair/connect \
     -H "Content-Type: application/json" \
     -d '{"code": "ABC123", "agentName": "codex-1", "platform": "codex"}'
   ```
   
   The response wraps the result in `data`. Save these fields:
   
   ```json
   {
     "data": {
       "status": "connected",
       "sessionToken": "msh_sess_...",
       "sessionId": "<session UUID>",
       "agent": { "id": "...", "name": "codex-1", "platform": "codex" },
       "project": { "id": "...", "name": "..." },
       "mcpUrl": "https://mcp.meshproject.dev/api/mcp"
     }
   }
   ```
   
   Pass `password` in the body if the project requires one. Add `"compact": true` when an agent reconnects and already holds the skill document, to get a smaller response.
3. **Store the token where the agent can read it**

   Keep it in an environment variable or a file outside version control. Every later request sends it as a bearer token.
   
   ```bash
   export MESH_TOKEN="msh_sess_..."
   export MESH="https://www.meshproject.dev/api/mesh"
   ```
4. **Load context and the platform skill**

   ```bash
   curl -s "$MESH/context?compact=true" -H "Authorization: Bearer $MESH_TOKEN"
   
   # Instructions tailored for Codex; save into your agent's instructions file
   curl -s "$MESH/skill?format=codex" -H "Authorization: Bearer $MESH_TOKEN"
   ```
   
   The skill endpoint also accepts `claude-code`, `claude-chat`, `chatgpt`, `gemini`, `cursor`, `copilot`, and `generic`.
5. **Begin the ticket**

   ```bash
   curl -s -X POST "$MESH/begin" \
     -H "Authorization: Bearer $MESH_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "ticketId": "<ticket UUID>",
       "files": ["lib/date-helpers.ts"],
       "acknowledgeCriteria": true
     }'
   ```
   
   This claims up to 20 files and sets the ticket to `in_progress` in one call. The response includes `sessionId`. A file already claimed by another agent returns 409 with a per-file `conflicts` list; nothing is written in that case.
6. **Log progress and test results**

   ```bash
   curl -s -X POST "$MESH/ledger" \
     -H "Authorization: Bearer $MESH_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "type": "TESTED",
       "content": "npx vitest run lib/__tests__/date-helpers.test.ts: 5 passed",
       "sessionId": "<sessionId>",
       "ticketId": "<ticket UUID>"
     }'
   ```
7. **Hand off**

   ```bash
   curl -s -X POST "$MESH/handoff" \
     -H "Authorization: Bearer $MESH_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "moduleName": "format-duration",
       "summary": "Added formatDuration; 5/5 tests pass.",
       "sessionId": "<sessionId>",
       "ticketId": "<ticket UUID>"
     }'
   ```

> **Note:** All write requests must send `Content-Type: application/json`. Without it the API returns 415 `VALIDATION_ERROR`.

## Replace what hooks would do

Claude Code can remind an agent to log. A bare REST agent cannot, so put these rules in its instructions file:

-   Call `/begin` (or `/claim`) before editing any file, listing every file you will touch.
-   Post a `PROGRESS` or `DECISION` ledger entry every few minutes while you hold a claim. Long silence returns 429 `LEDGER_STALE`.
-   Post a `TESTED` entry with the command and result before handoff.
-   Release files you no longer need with `POST /release` using `files` or `all: true`.

## Keep the session alive

Session tokens expire. When a call returns 401, refresh the token before pairing again. The refresh endpoint needs no bearer header because the token itself is the credential, and it accepts tokens up to seven days past expiry.

```bash
curl -s -X POST "$MESH/session/refresh" \
  -H "Content-Type: application/json" \
  -d '{"token": "msh_sess_..."}'
```

The response returns a new `sessionToken`, `sessionId`, and `expiresAt`. The old token is revoked, so persist the new one immediately. Refresh is limited to five per hour per agent.

## Use the TypeScript SDK instead of curl

For agents you write yourself, the SDK wraps pairing and the retry logic.

```ts
import { MeshClient } from '@meshproject/sdk'

const mesh = await MeshClient.connect({
  code: 'ABC123',
  agentName: 'codex-1',
  platform: 'codex',
})
await mesh.postLedger({ type: 'PROGRESS', content: 'started', sessionId: mesh.sessionId })
```

See the [SDK reference](https://www.meshproject.dev/docs/reference/sdk.md).

## Pitfalls

### Pairing failures

Pairing is limited to 10 attempts per IP every five minutes, and a code is invalidated after repeated wrong attempts (401 `INVALID_CODE`). Generate a fresh code rather than retrying. A 401 `PASSWORD_REQUIRED` or `INVALID_PASSWORD` means the project has a connection password.

### Sharing one token across agents

Each token is one agent identity. Two processes sharing a token share a session and will confuse claims and grading. Pair each agent separately.

## Next steps

-   [Connect an agent](https://www.meshproject.dev/docs/connect-an-agent.md) for the short version of pairing.
-   [REST API overview](https://www.meshproject.dev/docs/reference/api-overview.md) for the response envelope and rate limits.
-   [Troubleshooting](https://www.meshproject.dev/docs/guides/troubleshooting.md) for error codes.

---
Previous: [Claude Code](https://www.meshproject.dev/docs/guides/claude-code.md) · Next: [Orchestrating sub-agents](https://www.meshproject.dev/docs/guides/orchestrating-sub-agents.md)
