# How to Set Up and Authenticate OmniRoute Cloud Agents (Codex, Cursor, Devin, Jules)

> Easily set up and authenticate OmniRoute cloud agents like Codex, Cursor, Devin, and Jules. Learn how to create agent credentials and connect using the AgentCredentials object.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-07-19

---

**OmniRoute provides a modular Cloud Agent framework where you authenticate Codex, Cursor, Devin, and Jules by creating an `AgentCredentials` object containing an `apiKey` and passing it to provider-specific agent classes that inherit from `CloudAgentBase`.**

The OmniRoute repository (`diegosouzapw/OmniRoute`) ships a unified interface for orchestrating third-party AI agents through a modular Cloud Agent framework. To set up and authenticate OmniRoute cloud agents, you instantiate provider-specific classes—`CodexCloudAgent`, `CursorCloudAgent`, `DevinAgent`, and `JulesAgent`—and supply credentials explicitly via the `AgentCredentials` type. This design keeps authentication explicit and testable, ensuring your API keys never leak to the client while enabling seamless integration with OpenAI Codex, Cursor AI, Devin AI, and Google Jules.

## Understanding the Cloud Agent Architecture

OmniRoute abstracts cloud agents behind a uniform API defined in [`src/lib/cloudAgent/baseAgent.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/baseAgent.ts). The **`CloudAgentBase`** abstract class implements shared functionality such as ID generation, generic status mapping, and the public interface (`createTask`, `getStatus`, `sendMessage`, `approvePlan`, `listSources`). 

Concrete implementations reside in `src/lib/cloudAgent/agents/`:
- **`CodexCloudAgent`** handles OpenAI Codex Cloud REST calls.
- **`CursorCloudAgent`** manages Cursor Cloud Agents.
- **`DevinAgent`** interfaces with Devin AI.
- **`JulesAgent`** controls Google Jules sessions.

The **`CloudAgentRegistry`** in [`src/lib/cloudAgent/registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/registry.ts) acts as a factory, resolving provider IDs (`codex-cloud`, `cursor-cloud`, `devin`, `jules`) to the correct concrete class. Shared type definitions—including `CloudAgentTask`, `CloudAgentActivity`, and `CloudAgentStatus`—live in [`src/lib/cloudAgent/types.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/types.ts).

## Authentication Requirements and Credentials

All agents rely on the **`AgentCredentials`** type defined in [`src/lib/cloudAgent/credentials.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/credentials.ts). This interface requires:
- **`apiKey`**: A string obtained from the respective service dashboard (OpenAI, Cursor, Devin, or Google).
- **`baseUrl`** (optional): Override the default API endpoint (commonly used for Cursor staging environments).

Crucially, agents **do not** read environment variables directly. You must construct the credentials object and pass it to every method call. This explicit pattern ensures type safety and prevents accidental key exposure.

## Step-by-Step Setup for Each Provider

Below are minimal, runnable TypeScript snippets demonstrating how to configure credentials and instantiate each agent. Replace placeholder values with real API keys from your service dashboards.

### OpenAI Codex Cloud Agent

The `CodexCloudAgent` class in [`src/lib/cloudAgent/agents/codex.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/agents/codex.ts) implements the `POST /codex/cloud/tasks` endpoint and status polling logic.

```typescript
import { CodexCloudAgent } from '@omniroute/cloudAgent/agents/codex';
import type { AgentCredentials } from '@omniroute/cloudAgent/credentials';

const codex = new CodexCloudAgent();
const credentials: AgentCredentials = { 
  apiKey: process.env.CODEX_API_KEY || '' 
};

const task = await codex.createTask(
  {
    prompt: 'Explain why the sky is blue.',
    source: { repoUrl: 'https://github.com/example/repo', repoName: 'repo' },
    options: {}
  },
  credentials
);

console.log('Codex task created, external id:', task.externalId);

// Poll status until completed
let statusResult = await codex.getStatus(task.externalId, credentials);
while (statusResult.status !== 'COMPLETED') {
  await new Promise(r => setTimeout(r, 2_000));
  statusResult = await codex.getStatus(task.externalId, credentials);
}
console.log('Result:', statusResult.result);

```

### Cursor Cloud Agent

Implemented in [`src/lib/cloudAgent/agents/cursor.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/agents/cursor.ts), the **`CursorCloudAgent`** maps proprietary status enums to the shared `CLOUD_AGENT_STATUS` map. You may optionally override the `baseUrl` for staging environments.

```typescript
import { CursorCloudAgent } from '@omniroute/cloudAgent/agents/cursor';

const cursor = new CursorCloudAgent();
const credentials = { 
  apiKey: process.env.CURSOR_API_KEY || '',
  baseUrl: 'https://staging.api.cursor.com/v0' // Optional override
};

const task = await cursor.createTask(
  {
    prompt: 'Refactor this function to be async.',
    source: { repoUrl: 'https://github.com/example/repo', repoName: 'repo' },
    options: { autoCreatePr: true }
  },
  credentials
);

console.log('Cursor task created, external id:', task.externalId);

```

### Devin AI Agent

The `DevinAgent` in [`src/lib/cloudAgent/agents/devin.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/agents/devin.ts) posts to `https://api.devin.ai/v1/sessions` and translates provider-specific status codes via the `mapStatus` method.

```typescript
import { DevinAgent } from '@omniroute/cloudAgent/agents/devin';

const devin = new DevinAgent();
const credentials = { apiKey: process.env.DEVIN_API_KEY || '' };

const task = await devin.createTask(
  {
    prompt: 'Write a unit test for function foo().',
    source: { repoUrl: 'https://github.com/example/repo', repoName: 'repo' },
    options: {}
  },
  credentials
);

console.log('Devin task created, external id:', task.externalId);

```

### Google Jules Agent

Unique among the four, **`JulesAgent`** (in [`src/lib/cloudAgent/agents/jules.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/agents/jules.ts)) supports plan approval workflows via the `approvePlan` method. It constructs Google-specific source resources (`sources/github/<owner>/<repo>`) and handles the plan-approval endpoint.

```typescript
import { JulesAgent } from '@omniroute/cloudAgent/agents/jules';

const jules = new JulesAgent();
const credentials = { apiKey: process.env.JULES_API_KEY || '' };

const task = await jules.createTask(
  {
    prompt: 'Add type safety to this TypeScript file.',
    source: {
      repoUrl: 'https://github.com/example/repo',
      repoName: 'my-repo',
      branch: 'main'
    },
    options: { autoCreatePr: true, planApprovalRequired: true }
  },
  credentials
);

console.log('Jules session created, id:', task.externalId);

// Approve the generated plan
await jules.approvePlan(task.externalId, credentials);

```

## Factory Pattern with CloudAgentRegistry

If you prefer dynamic resolution over hard-coded imports, use the **`CloudAgentRegistry`** from [`src/lib/cloudAgent/registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/registry.ts). This factory returns the appropriate agent instance based on a provider ID string.

```typescript
import { CloudAgentRegistry } from '@omniroute/cloudAgent/registry';

const registry = new CloudAgentRegistry();
const agent = registry.getAgent('cursor-cloud'); // Returns CursorCloudAgent instance
const credentials = { apiKey: process.env.CURSOR_API_KEY || '' };

const task = await agent.createTask({ /* ... */ }, credentials);

```

Supported provider IDs include:
- `codex-cloud`
- `cursor-cloud`
- `devin`
- `jules`

## Summary

- OmniRoute cloud agents inherit from `CloudAgentBase` and implement provider-specific REST calls in `src/lib/cloudAgent/agents/`.
- Authentication requires an **`AgentCredentials`** object with an **`apiKey`** (and optional **`baseUrl`** for Cursor) passed explicitly to each method.
- The four supported providers are instantiated via **`CodexCloudAgent`**, **`CursorCloudAgent`**, **`DevinAgent`**, and **`JulesAgent`**.
- Use **`CloudAgentRegistry`** to resolve agent instances dynamically using provider IDs like `codex-cloud` or `jules`.
- All agents expose a uniform interface (`createTask`, `getStatus`, `approvePlan`) while handling provider-specific headers and endpoints internally.

## Frequently Asked Questions

### What authentication format does OmniRoute require for cloud agents?

OmniRoute expects an **`AgentCredentials`** object containing at least an **`apiKey`** string. For Cursor, you may optionally include a **`baseUrl`** to override the default endpoint. According to the source code in [`src/lib/cloudAgent/credentials.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/credentials.ts), the agents do not read environment variables directly; you must pass the credentials object to every method call.

### How do I switch between different AI providers without changing my code?

Use the **`CloudAgentRegistry`** class from [`src/lib/cloudAgent/registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/registry.ts). By calling `registry.getAgent(providerId)` with identifiers like `codex-cloud`, `cursor-cloud`, `devin`, or `jules`, you obtain the correct instantiated agent without hard-coding the specific class imports, enabling provider-agnostic workflows.

### Does OmniRoute store my API keys or send them to the client?

No. The agent classes in `src/lib/cloudAgent/agents/` inject credentials into HTTP headers during REST calls to the respective services (Codex, Cursor, Devin, Jules). The keys remain server-side and are never exposed to the client, as implemented in the base class and provider-specific agents.

### Which OmniRoute cloud agent supports plan approval workflows?

The **`JulesAgent`** class in [`src/lib/cloudAgent/agents/jules.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/cloudAgent/agents/jules.ts) specifically implements the **`approvePlan`** method, which calls a dedicated endpoint to approve generated plans after task creation. This capability is unique to the Google Jules integration among the four supported agents.