Cloud Agent Integrations in OmniRoute: How External AI Services Are Implemented as First-Class Providers

OmniRoute integrates five cloud agents (Jules, Devin, Codex, Cursor, and Cursor-cloud) through a pluggable framework defined in src/lib/cloudAgent/baseAgent.ts, where each agent extends CloudAgentBase and implements four lifecycle methods: createTask, getStatus, sendMessage, and listSources.

The cloud agent integrations in OmniRoute transform external AI coding services into native routing targets. Rather than treating these platforms as black-box APIs, OmniRoute's architecture—as implemented in diegosouzapw/OmniRoute—abstracts them through a common interface that inherits the router's resilience patterns, credential encryption, and task persistence.

Supported Cloud Agents in OmniRoute

The current release (v3.8.50) ships with five built-in cloud agent integrations. Each maps to a unique provider ID and serves distinct AI-assisted development workflows.

Agent Provider ID Core Purpose
Jules jules Connects to the Jules.ai cloud API for chat-completion style interactions
Devin devin Drives the Devin CLI service for autonomous code-generation tasks
Codex codex Calls the OpenAI Codex endpoint via a thin TypeScript wrapper
Cursor cursor Uses Cursor's public REST API with API-key-only authentication
Cursor-cloud cursor-cloud OAuth-free variant added in v3.8.50 for streamlined background agents

The Cloud Agent Base Class Architecture

All cloud agent integrations in OmniRoute derive from a single abstract class defined in src/lib/cloudAgent/baseAgent.ts. This common abstraction enforces a four-method contract that every concrete agent must fulfill.

Required Lifecycle Methods

Method Signature Purpose
createTask (prompt: string, …): Promise<string> Starts a remote task and stores the external task ID
getStatus (taskId: string): Promise<CloudAgentStatus> Polls the remote service and maps status to CREATING, RUNNING, FINISHED, or ERROR
sendMessage (taskId: string, message: string): Promise<void> Sends incremental input to an already-running task
listSources (taskId: string): Promise<SourceFile[]> Retrieves generated artifacts or source files

The CloudAgentBase constructor handles credential decryption and exposes baseUrl and authentication headers to subclasses, eliminating redundant security logic across agent implementations.

How the Framework Is Wired Together

Four core modules orchestrate cloud agent integrations in OmniRoute:

src/lib/cloudAgent/registry.ts — Provider Resolution

  • Maintains a map providerId → CloudAgentClass
  • Factory method instantiates agents with decrypted credentials
  • New agents register via cloudAgentRegistry.register('id', AgentClass)

src/lib/cloudAgent/credentials.ts — Secure Authentication

  • Encrypts API keys and OAuth tokens in the cloud_agent_credentials SQLite table
  • Decrypts on agent instantiation
  • Supports per-provider credential schemas

src/lib/cloudAgent/db.ts — Task Persistence

  • Stores task records in cloud_agent_tasks linking OmniRoute task IDs to external external_id values
  • Enables asynchronous polling and UI state synchronization

src/lib/cloudAgent/api.ts and src/lib/cloudAgent/index.ts — Public REST API

  • Exposes endpoints under /api/v1/agents/*
  • Validates inputs with Zod schemas
  • Enforces authentication before delegating to agent implementations

Agent Implementation Pattern

Each concrete agent follows an identical skeleton. Here is the structural pattern from src/lib/cloudAgent/agents/jules.ts, agents/devin.ts, agents/cursor.ts, and agents/codex.ts:

export class XxxAgent extends CloudAgentBase {
  async createTask(prompt: string, …): Promise<string> {
    // HTTP POST to provider endpoint
    // Store returned external ID in cloud_agent_tasks table
  }

  async getStatus(taskId: string): Promise<CloudAgentStatus> {
    // HTTP GET to provider status endpoint
    // Map provider-specific enum to CloudAgentStatus union
  }

  async sendMessage(taskId: string, msg: string): Promise<void> {
    // HTTP PATCH or POST for incremental prompts
  }

  async listSources(taskId: string): Promise<SourceFile[]> {
    // HTTP GET to fetch generated files or code snippets
  }
}

All HTTP traffic routes through open-sse/executors/, inheriting OmniRoute's retry logic, circuit breakers, and rate limiting. Errors are sanitized through open-sse/utils/error.ts before client exposure.

Request Flow Through the Cloud Agent System

Understanding the end-to-end flow clarifies how cloud agent integrations in OmniRoute maintain stateful, resilient interactions with external services.

  1. Client submits taskPOST /api/v1/agents/tasks with provider ID and prompt
  2. API handler validates payload with Zod, resolves provider from registry
  3. Agent instantiation → registry returns concrete class with decrypted credentials
  4. createTask execution → HTTP POST to remote service, external ID persisted to cloud_agent_tasks
  5. Polling loopGET /agents/tasks/:id invokes getStatus, updates database, returns to client
  6. Continued interactionsendMessage for follow-up prompts, listSources for artifact retrieval

Practical Code Examples

Creating a Task with the Jules Agent

import { cloudAgentRegistry } from '@/lib/cloudAgent/registry';

const agent = cloudAgentRegistry.get('jules'); // returns JulesAgent instance
const externalId = await agent.createTask('Write a TypeScript utility for parsing JSON streams');
// externalId stored in cloud_agent_tasks with status 'CREATING'

Source: src/lib/cloudAgent/registry.ts

Polling Task Status and Retrieving Results

const status = await agent.getStatus(externalId);

if (status === 'FINISHED') {
  const files = await agent.listSources(externalId);
  // files: Array<{ path: string; content: string }>
} else if (status === 'ERROR') {
  // Handle failure per open-sse/utils/error.ts patterns
}

Source: src/lib/cloudAgent/agents/jules.ts

Registering a New Custom Agent

// src/lib/cloudAgent/registry.ts
import { MyAIAgent } from './agents/myai';

cloudAgentRegistry.register('myai', MyAIAgent);

Only three steps required: extend CloudAgentBase, register in registry.ts, and add credential definition if needed. No modifications to core routing logic.

Key Files for Cloud Agent Integrations in OmniRoute

File Role
src/lib/cloudAgent/baseAgent.ts Abstract base class defining the cloud-agent contract
src/lib/cloudAgent/registry.ts Provider-ID to implementation mapping and factory
src/lib/cloudAgent/credentials.ts Encrypted storage and retrieval of API keys/tokens
src/lib/cloudAgent/db.ts SQLite persistence layer for tasks and credentials
src/lib/cloudAgent/api.ts Public HTTP endpoints for agent operations
src/lib/cloudAgent/agents/jules.ts Jules.ai integration implementation
src/lib/cloudAgent/agents/devin.ts Devin CLI service integration
src/lib/cloudAgent/agents/cursor.ts Cursor REST API integration
src/lib/cloudAgent/agents/codex.ts OpenAI Codex wrapper implementation

Summary

  • OmniRoute supports five cloud agent integrations (Jules, Devin, Codex, Cursor, Cursor-cloud) through a unified framework
  • The CloudAgentBase abstraction in src/lib/cloudAgent/baseAgent.ts enforces consistent lifecycle methods across all providers
  • Registry pattern enables runtime provider resolution without core router modifications
  • Encrypted credential storage and SQLite task persistence provide production-grade security and state management
  • New agents require only three implementation steps; the framework inherits OmniRoute's retry, circuit-breaker, and rate-limiting capabilities automatically

Frequently Asked Questions

How do I add a new cloud agent integration to OmniRoute?

Extend CloudAgentBase from src/lib/cloudAgent/baseAgent.ts, implement the four required methods (createTask, getStatus, sendMessage, listSources), then register your class in src/lib/cloudAgent/registry.ts with cloudAgentRegistry.register('your-id', YourAgentClass). Add credential definitions in credentials.ts if your service requires API keys or tokens.

Where are cloud agent API keys stored in OmniRoute?

API keys and OAuth tokens are encrypted in the cloud_agent_credentials SQLite table, managed by src/lib/cloudAgent/credentials.ts. The CloudAgentBase constructor automatically decrypts credentials when instantiating agent classes, exposing baseUrl and auth headers to implementations without exposing secrets in code.

What happens when a cloud agent task fails?

Errors propagate through open-sse/utils/error.ts for sanitization before reaching clients. The getStatus method returns ERROR status, which persists in the cloud_agent_tasks table. All HTTP calls inherit retry logic and circuit-breaker patterns from OmniRoute's executor layer in open-sse/executors/.

How does OmniRoute track cloud agent task state across restarts?

The cloud_agent_tasks table in src/lib/cloudAgent/db.ts persists the mapping between OmniRoute task IDs and provider external_id values. This allows polling endpoints to resume status checks after service restarts, and enables the UI to reconstruct task history from durable storage.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →