AI brings intelligence. Workflows bring reliability. Orkes brings them together. Agents and workflows are first-class citizens on a single platform, allowing organizations to build applications that combine adaptive decision-making with predictable, governed execution.
Explainability
Decisions you can trust and understand
AI introduces uncertainty in your business. Orkes helps teams understand how decisions are made, why outcomes occur, and where processes can be improved, bringing trust and transparency to AI-powered operations.
Durability
Built for Critical Operations
Durability is built into every execution. Your operations won't fail because a service fails, a worker crashes, or an approval takes days. Orkes was built to run long-lived, mission-critical operations at scale.
Open Source
Open Source and Enterprise Ready
Originated at Netflix. Built on the foundation of Conductor and extended to be enterprise ready with trusted governance, security, observability, and operational reliability.
Build Agents and Workflows
Design Processes
Design workflows visually or in code. Build AI agents with your preferred models, tools, and frameworks
Open and Extensible
Build with the Conductor SDK or bring LangGraph, OpenAI Agents SDK, Google ADK, CrewAI, or your own agents.
Composable by Design
Agents and workflows invoke each other while sharing prompts, tools, models, forms, and platform services.
Run them durably
Observe and Govern
Complete visibility and control over your entire orchestration platform
Real-time Monitoring
Track every execution in real-time
Explainability
Understand decisions taken
Analytics
Detailed performance metrics
Access Control
Fine-grained RBAC policies
Audit Logs
Complete audit trail
Guardrails
Validate every input and output
Powered by Open Source
Developer First by Design
Simple APIs, SDKs in your favorite language, and integrations with the tools
you already use.
Native SDKs
Develop agent and workflows with native SDKs for Java, Python, Go, JavaScript, TypeScript, C#, and more
AI Coding Agent Ready
Use skills.md to give Claude Code, Codex, Cursor and other coding agents the context they need to build agents and workflows correctly.
REST APIs & CLI
Create, test, deploy, and manage agents and workflows programmatically using REST APIs and CLI
Open Source Core
Built on battle-tested Conductor OSS, originally open sourced by Netflix
import osfrom conductor.ai.agents import Agent, AgentRuntime, Strategy, toolfrom conductor.client.configuration.configuration import ConfigurationSERVER_URL = os.environ.get("CONDUCTOR_SERVER_URL", "http://localhost:8080/api")LLM_MODEL = os.environ.get("CONDUCTOR_AGENT_LLM_MODEL", "openai/gpt-4o-mini")@tooldef check_balance(account_id: str) -> dict: """Check the balance of a bank account.""" return {"account_id": account_id, "balance": 5432.10, "currency": "USD"}@tooldef lookup_order(order_id: str) -> dict: """Look up the status of an order.""" return {"order_id": order_id, "status": "shipped", "eta": "2 days"}billing = Agent( name="billing", model=LLM_MODEL, instructions="Handle billing questions: balances, payments, invoices.", tools=[check_balance],)orders = Agent( name="orders", model=LLM_MODEL, instructions="Handle order questions: status, shipping, returns.", tools=[lookup_order],)support = Agent( name="support", model=LLM_MODEL, instructions="Route each request to the right specialist.", agents=[billing, orders], strategy=Strategy.HANDOFF,)if __name__ == "__main__": with AgentRuntime(Configuration(server_api_url=SERVER_URL)) as runtime: result = runtime.run(support, "What's the balance on account ACC-123?") result.print_result()
import java.util.List;import java.util.Map;import io.orkes.conductor.client.ApiClient;import org.conductoross.conductor.ai.Agent;import org.conductoross.conductor.ai.AgentRuntime;import org.conductoross.conductor.ai.annotations.Tool;import org.conductoross.conductor.ai.enums.Strategy;import org.conductoross.conductor.ai.internal.ToolRegistry;import org.conductoross.conductor.ai.model.AgentResult;import org.conductoross.conductor.ai.model.ToolDef;public class HandoffAgent { public static class BillingTools { @Tool(name = "check_balance", description = "Check the balance of a bank account.") public Map<String, Object> checkBalance(String accountId) { return Map.of("account_id", accountId, "balance", 5432.10, "currency", "USD"); } } public static class OrderTools { @Tool(name = "lookup_order", description = "Look up the status of an order.") public Map<String, Object> lookupOrder(String orderId) { return Map.of("order_id", orderId, "status", "shipped", "eta", "2 days"); } } public static void main(String[] args) { String serverUrl = System.getenv() .getOrDefault("CONDUCTOR_SERVER_URL", "http://localhost:8080/api"); String llmModel = System.getenv() .getOrDefault("CONDUCTOR_AGENT_LLM_MODEL", "openai/gpt-4o-mini"); List<ToolDef> billingTools = ToolRegistry.fromInstance(new BillingTools()); List<ToolDef> orderTools = ToolRegistry.fromInstance(new OrderTools()); Agent billing = Agent.builder() .name("billing") .model(llmModel) .instructions("Handle billing questions: balances, payments, invoices.") .tools(billingTools) .build(); Agent orders = Agent.builder() .name("orders") .model(llmModel) .instructions("Handle order questions: status, shipping, returns.") .tools(orderTools) .build(); Agent support = Agent.builder() .name("support") .model(llmModel) .instructions("Route each request to the right specialist.") .agents(billing, orders) .strategy(Strategy.HANDOFF) .build(); AgentRuntime runtime = new AgentRuntime(new ApiClient(serverUrl)); AgentResult result = runtime.run(support, "What's the balance on account ACC-123?"); result.printResult(); runtime.shutdown(); }}
import { Agent, AgentRuntime, tool } from '@io-orkes/conductor-javascript/agents';const SERVER_URL = process.env.CONDUCTOR_SERVER_URL ?? 'http://localhost:8080/api';const LLM_MODEL = process.env.CONDUCTOR_AGENT_LLM_MODEL ?? 'openai/gpt-4o-mini';const checkBalance = tool( async (args: { accountId: string }) => ({ account_id: args.accountId, balance: 5432.1, currency: 'USD', }), { name: 'check_balance', description: 'Check the balance of a bank account.', inputSchema: { type: 'object', properties: { accountId: { type: 'string', description: 'The account ID to check' } }, required: ['accountId'], }, },);const lookupOrder = tool( async (args: { orderId: string }) => ({ order_id: args.orderId, status: 'shipped', eta: '2 days', }), { name: 'lookup_order', description: 'Look up the status of an order.', inputSchema: { type: 'object', properties: { orderId: { type: 'string', description: 'The order ID to look up' } }, required: ['orderId'], }, },);const billing = new Agent({ name: 'billing', model: LLM_MODEL, instructions: 'Handle billing questions: balances, payments, invoices.', tools: [checkBalance],});const orders = new Agent({ name: 'orders', model: LLM_MODEL, instructions: 'Handle order questions: status, shipping, returns.', tools: [lookupOrder],});const support = new Agent({ name: 'support', model: LLM_MODEL, instructions: 'Route each request to the right specialist.', agents: [billing, orders], strategy: 'handoff',});async function main() { const runtime = new AgentRuntime({ serverUrl: SERVER_URL }); try { const result = await runtime.run(support, "What's the balance on account ACC-123?"); result.printResult(); } finally { await runtime.shutdown(); }}main().catch((err) => { console.error(err); process.exit(1);});
using Conductor.AI;var serverUrl = Environment.GetEnvironmentVariable("CONDUCTOR_SERVER_URL") ?? "http://localhost:8080/api";var llmModel = Environment.GetEnvironmentVariable("CONDUCTOR_AGENT_LLM_MODEL") ?? "openai/gpt-4o-mini";var billingTools = ToolRegistry.FromInstance(new BillingTools());var orderTools = ToolRegistry.FromInstance(new OrderTools());var billing = new Agent("billing"){ Model = llmModel, Instructions = "Handle billing questions: balances, payments, invoices.", Tools = billingTools,};var orders = new Agent("orders"){ Model = llmModel, Instructions = "Handle order questions: status, shipping, returns.", Tools = orderTools,};var support = new Agent("support"){ Model = llmModel, Instructions = "Route each request to the right specialist.", Agents = [billing, orders], Strategy = Strategy.Handoff,};await using var runtime = new AgentRuntime(new AgentRuntimeOptions { ServerUrl = serverUrl });var result = await runtime.RunAsync(support, "What's the balance on account ACC-123?");result.PrintResult();internal sealed class BillingTools{ [Tool("Check the balance of a bank account.")] public Dictionary<string, object> CheckBalance(string accountId) => new() { ["account_id"] = accountId, ["balance"] = 5432.10, ["currency"] = "USD" };}internal sealed class OrderTools{ [Tool("Look up the status of an order.")] public Dictionary<string, object> LookupOrder(string orderId) => new() { ["order_id"] = orderId, ["status"] = "shipped", ["eta"] = "2 days" };}
import { Agent, AgentRuntime, tool } from '@io-orkes/conductor-javascript/agents';const SERVER_URL = process.env.CONDUCTOR_SERVER_URL ?? 'http://localhost:8080/api';const LLM_MODEL = process.env.CONDUCTOR_AGENT_LLM_MODEL ?? 'openai/gpt-4o-mini';const checkBalance = tool( async ({ accountId }) => ({ account_id: accountId, balance: 5432.1, currency: 'USD', }), { name: 'check_balance', description: 'Check the balance of a bank account.', inputSchema: { type: 'object', properties: { accountId: { type: 'string', description: 'The account ID to check' } }, required: ['accountId'], }, },);const lookupOrder = tool( async ({ orderId }) => ({ order_id: orderId, status: 'shipped', eta: '2 days', }), { name: 'lookup_order', description: 'Look up the status of an order.', inputSchema: { type: 'object', properties: { orderId: { type: 'string', description: 'The order ID to look up' } }, required: ['orderId'], }, },);const billing = new Agent({ name: 'billing', model: LLM_MODEL, instructions: 'Handle billing questions: balances, payments, invoices.', tools: [checkBalance],});const orders = new Agent({ name: 'orders', model: LLM_MODEL, instructions: 'Handle order questions: status, shipping, returns.', tools: [lookupOrder],});const support = new Agent({ name: 'support', model: LLM_MODEL, instructions: 'Route each request to the right specialist.', agents: [billing, orders], strategy: 'handoff',});async function main() { const runtime = new AgentRuntime({ serverUrl: SERVER_URL }); try { const result = await runtime.run(support, "What's the balance on account ACC-123?"); result.printResult(); } finally { await runtime.shutdown(); }}main().catch((err) => { console.error(err); process.exit(1);});
require 'conductor'config = Conductor::Configuration.new( server_api_url: ENV.fetch('CONDUCTOR_SERVER_URL', 'http://localhost:8080/api'))executor = Conductor::Workflow::WorkflowExecutor.new(config)# -- Define the workflow -----------------------------------------------------workflow = Conductor.workflow :order_fulfillment, version: 1, executor: executor do description 'Reserve stock, then charge the customer' simple :check_inventory, sku: '${workflow.input.sku}', quantity: '${workflow.input.quantity}' simple :charge_payment, order_id: '${workflow.input.order_id}', amount: '${workflow.input.amount}' # NOTE: the DSL names each task's reference "<task>_ref", so output mappings # must use charge_payment_ref, not charge_payment. output confirmation: '${charge_payment_ref.output.confirmation}', warehouse: '${check_inventory_ref.output.warehouse}'endexecutor.register_workflow(workflow, overwrite: true)# -- Implement the steps -----------------------------------------------------check_inventory = Conductor::Worker.worker_task('check_inventory', poll_interval: 1) do |task| { 'in_stock' => true, 'warehouse' => 'us-east-1', 'sku' => task.input_data['sku'] }endcharge_payment = Conductor::Worker.worker_task('charge_payment', poll_interval: 1) do |task| { 'confirmation' => "PAY-#{task.input_data['order_id']}", 'amount' => task.input_data['amount'] }end# scan_for_annotated_workers: false — worker_task already put these in the# global registry; without this the handler would start a second poller each.handler = Conductor::Worker::TaskHandler.new( workers: [check_inventory, charge_payment], configuration: config, scan_for_annotated_workers: false)handler.start# -- Run it ------------------------------------------------------------------result = executor.execute_and_wait( 'order_fulfillment', input: { 'sku' => 'SKU-42', 'quantity' => 2, 'order_id' => 'ORD-123', 'amount' => 79.98 }, timeout_seconds: 60)puts "status: #{result.status}"puts "confirmation: #{result.output['confirmation']}"puts "warehouse: #{result.output['warehouse']}"handler.stop
use std::time::Duration;use conductor::{ client::ConductorClient, configuration::Configuration, error::Result, models::{StartWorkflowRequest, WorkflowDef, WorkflowTask}, worker::TaskHandler,};use conductor_macros::worker;#[worker(name = "check_inventory")]async fn check_inventory(sku: String, quantity: i32) -> serde_json::Value { serde_json::json!({ "in_stock": true, "warehouse": "us-east-1", "sku": sku, "quantity": quantity })}#[worker(name = "charge_payment")]async fn charge_payment(order_id: String, amount: f64) -> serde_json::Value { serde_json::json!({ "confirmation": format!("PAY-{order_id}"), "amount": amount })}#[tokio::main]async fn main() -> Result<()> { let config = Configuration::default(); // reads CONDUCTOR_SERVER_URL let client = ConductorClient::new(config.clone())?; // -- Define the workflow ------------------------------------------------- let workflow = WorkflowDef::new("order_fulfillment") .with_description("Reserve stock, then charge the customer") .with_version(1) .with_task( WorkflowTask::simple("check_inventory", "inventory") .with_input_param("sku", "${workflow.input.sku}") .with_input_param("quantity", "${workflow.input.quantity}"), ) .with_task( WorkflowTask::simple("charge_payment", "payment") .with_input_param("order_id", "${workflow.input.order_id}") .with_input_param("amount", "${workflow.input.amount}"), ) // NOTE: the #[worker] macro wraps a worker's return value under a // "result" key, so task outputs are read as <ref>.output.result.<field>. .with_output_param("confirmation", "${payment.output.result.confirmation}") .with_output_param("warehouse", "${inventory.output.result.warehouse}"); client .metadata_client() .register_or_update_workflow_def(&workflow, true) .await?; // -- Serve the steps ----------------------------------------------------- let mut handler = TaskHandler::new(config.clone())?; handler.add_worker(check_inventory_worker()); handler.add_worker(charge_payment_worker()); handler.start().await?; // -- Run it -------------------------------------------------------------- let request = StartWorkflowRequest::new("order_fulfillment") .with_version(1) .with_input_value("sku", "SKU-42") .with_input_value("quantity", 2) .with_input_value("order_id", "ORD-123") .with_input_value("amount", 79.98); let execution_id = client.workflow_client().start_workflow(&request).await?; let mut wf = client.workflow_client().get_workflow(&execution_id, false).await?; for _ in 0..60 { if wf.is_terminal() { break; } tokio::time::sleep(Duration::from_secs(1)).await; wf = client.workflow_client().get_workflow(&execution_id, false).await?; } println!("status: {:?}", wf.status); println!("confirmation: {}", wf.output.get("confirmation").and_then(|v| v.as_str()).unwrap_or("-")); println!("warehouse: {}", wf.output.get("warehouse").and_then(|v| v.as_str()).unwrap_or("-")); handler.stop().await?; Ok(())}
Enterprise Ready, Battle Tested
Trusted by Fortune 500 companies to handle their most critical workflows.
Up to 99.99%
Automatic state persistence and recovery on failures.
1B+
Workflows Executed Daily
Flexible deployments
AWS, Azure, GCP or on-prem
Mission Critical Support
Enterprise Plans
What our customers say
"Orkes has been instrumental in increasing developer agility, creating cost efficiencies, and building highly reliable and secure applications. We’re so impressed with the results that we are migrating more workflows from other platforms to Orkes and initiating all flows on Orkes."
Thisara Alawala,
Lead Architect, Foxtel
"We didn’t want data management; we wanted a powerful microservice orchestration engine. After a careful analysis, Normalyze chose Conductor delivered by Orkes Cloud."
Ravi Ithal,
Founder & CTO, Normalyze
"I can’t stress enough how much Orkes Cloud has helped us over the past year to get our microservices efforts off the ground and accelerate this process. And our development teams love Orkes because they can quickly make the microservices they need. Our development teams can automate anything they want. It’s very empowering,"
Andy French,
AVP of Platform Automation, United Wholesale Mortgage
"One of the things that really attracted me to Orkes Conductor is that the infrastructure is already in place. As a CTO, I want my team to build very specific tasks and applications rather than spend the time building infrastructure, which Orkes Conductor allows them to do."
Andres Garcia,
CTO, Florence Healthcare
Explore the Platform
Orkes Conductor
Unified platform for agents and workflows. Enables you to build AI powered applications that combine AI reasoning with determinism.