---
description: Write, run, and verify your first Conductor workflow and worker in Python, Java, TypeScript/JavaScript, C#, or Rust.
---
# Your First Workflow & Worker
**Outcome:** a `greetings` workflow that queues a `greet` task and returns `Hello Conductor` from a worker.
**Time:** about 5 minutes.
Complete [Connect to Conductor](connect.md) first. This guide uses the SDK connection variables configured there: `CONDUCTOR_SERVER_URL`, plus `CONDUCTOR_AUTH_KEY` and `CONDUCTOR_AUTH_SECRET` when your server requires them.
## How a worker runs
In this quickstart you build two things: a **workflow** named `greetings` — the durable definition that Conductor executes — and a **worker** — a function in your code that performs one task inside it.
The workflow has a single task of type `SIMPLE`, which means the work is done by your code rather than by one of Conductor's built-in tasks. Every `SIMPLE` task has a task type — here, `greet`. When a running workflow reaches that task, Conductor places it on a queue for that task type. Your worker polls the `greet` queue, runs your business logic, and reports back `COMPLETED` or `FAILED`. Conductor durably persists the result, then advances the workflow to its next task.
Two rules follow from this design:
- The task type must match exactly between the workflow definition and the worker — otherwise the task sits on a queue that nothing polls.
- Workers run as ordinary processes in your own infrastructure and deploy and scale independently of the Conductor server. Conductor guarantees at-least-once delivery, meaning the same task can be delivered again after a failure or timeout — so write workers to be idempotent, where running the same task twice produces the same result.
```mermaid
flowchart LR
subgraph server["Conductor server"]
wf["greetings workflow"] --> task["greet task (SIMPLE)"]
end
queue[["greet queue"]]
subgraph worker["Your worker"]
fn["greet(name)
your business logic"]
end
task -- "queues by task type" --> queue
fn -- "polls" --> queue
fn -- "reports COMPLETED / FAILED
Conductor persists result, advances workflow" --> task
```
## Language-specific quickstart
Choose a language to reveal one complete `greet` worker and the matching `greetings` workflow. The examples are adapted from the maintained SDK hello-world worker examples.
Choose a language to reveal its install, worker, workflow, and run steps.
1. Install Python support
```bash pip install conductor-python ```2. Save the worker and workflow app
Save as `quickstart.py`: ```python from conductor.client.automator.task_handler import TaskHandler from conductor.client.configuration.configuration import Configuration from conductor.client.orkes_clients import OrkesClients from conductor.client.workflow.conductor_workflow import ConductorWorkflow from conductor.client.worker.worker_task import worker_task @worker_task(task_definition_name="greet", register_task_def=True) def greet(name: str) -> dict: return {"result": f"Hello {name}"} def main(): config = Configuration() clients = OrkesClients(configuration=config) executor = clients.get_workflow_executor() workflow = ConductorWorkflow(name="greetings", version=1, executor=executor) greet_task = greet(task_ref_name="greet_ref", name=workflow.input("name")) workflow >> greet_task workflow.output_parameters({"result": greet_task.output("result")}) workflow.register(overwrite=True) with TaskHandler(configuration=config, scan_for_annotated_workers=True) as handler: handler.start_processes() run = executor.execute(name="greetings", version=1, workflow_input={"name": "Conductor"}) print(run.output["result"]) if __name__ == "__main__": main() ```3. Run and verify
```bash python quickstart.py # Hello Conductor ``` See the [Python SDK guide](../documentation/clientsdks/python-sdk.md) for worker configuration and production patterns.1. Install Java support
Add the SDK dependency to your Gradle project: ```groovy dependencies { implementation 'org.conductoross:conductor-client:5.0.1' } ```2. Save the worker and workflow app
Save as `Main.java`: ```java import com.netflix.conductor.client.automator.TaskRunnerConfigurer; import com.netflix.conductor.client.http.ConductorClient; import com.netflix.conductor.client.http.TaskClient; import com.netflix.conductor.client.http.WorkflowClient; import com.netflix.conductor.client.worker.Worker; import com.netflix.conductor.common.metadata.tasks.Task; import com.netflix.conductor.common.metadata.tasks.TaskResult; import com.netflix.conductor.sdk.workflow.def.ConductorWorkflow; import com.netflix.conductor.sdk.workflow.def.tasks.SimpleTask; import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor; import java.util.List; import java.util.Map; class GreetWorker implements Worker { @Override public String getTaskDefName() { return "greet"; } @Override public TaskResult execute(Task task) { String name = (String) task.getInputData().get("name"); TaskResult result = new TaskResult(task); result.setStatus(TaskResult.Status.COMPLETED); result.addOutputData("result", "Hello " + name); return result; } } public class Main { public static void main(String[] args) { String serverUrl = System.getenv().getOrDefault( "CONDUCTOR_SERVER_URL", "http://localhost:8080/api"); ConductorClient client = ConductorClient.builder().basePath(serverUrl).build(); WorkflowExecutor executor = new WorkflowExecutor(client); ConductorWorkflow workflow = new ConductorWorkflow<>(executor); workflow.setName("greetings"); workflow.setVersion(1); SimpleTask greetTask = new SimpleTask("greet", "greet_ref"); greetTask.input("name", "${workflow.input.name}"); workflow.add(greetTask); workflow.registerWorkflow(true, true); TaskClient taskClient = new TaskClient(client); new TaskRunnerConfigurer.Builder(taskClient, List.of(new GreetWorker())) .withThreadCount(10) .build() .init(); WorkflowClient workflowClient = new WorkflowClient(client); String workflowId = workflowClient.startWorkflow( "greetings", 1, "", Map.of("name", "Conductor")); System.out.println("Started workflow: " + workflowId); } } ```3. Run and verify
Run the class with your Gradle application task, then inspect the completed `greet_ref` task in the `greetings` execution. Its output is: ```text Hello Conductor ``` See the [Java SDK guide](../documentation/clientsdks/java-sdk.md) for complete imports and worker configuration.1. Install TypeScript / JavaScript support
```bash npm install @io-orkes/conductor-javascript ```2. Save the worker and workflow app
Save as `quickstart.ts`: ```typescript import { OrkesClients, ConductorWorkflow, TaskHandler, worker, simpleTask, } from "@io-orkes/conductor-javascript"; import type { Task } from "@io-orkes/conductor-javascript"; @worker({ taskDefName: "greet" }) async function greet(task: Task) { return { status: "COMPLETED" as const, outputData: { result: `Hello ${task.inputData.name}` }, }; } async function main() { const clients = await OrkesClients.from(); const executor = clients.getWorkflowClient(); const workflow = new ConductorWorkflow(executor, "greetings") .add(simpleTask("greet_ref", "greet", { name: "${workflow.input.name}" })) .outputParameters({ result: "${greet_ref.output.result}" }); await workflow.register(); const handler = new TaskHandler({ client: clients.getClient(), scanForDecorated: true }); await handler.startWorkers(); const run = await workflow.execute({ name: "Conductor" }); console.log(run.output?.result); await handler.stopWorkers(); } main(); ```3. Run and verify
```bash npx ts-node quickstart.ts # Hello Conductor ``` See the [JavaScript SDK guide](../documentation/clientsdks/js-sdk.md) for TypeScript 5 decorators, worker health, and production configuration.1. Install C# support
```bash dotnet add package conductor-csharp ```2. Save and start the worker
Save as `GreetWorker.cs`: ```csharp using Conductor.Client.Extensions; using Conductor.Client.Interfaces; using Conductor.Client.Models; using Conductor.Client.Worker; using Task = Conductor.Client.Models.Task; public class GreetWorker : IWorkflowTask { public string TaskType => "greet"; public WorkflowTaskExecutorConfiguration WorkerSettings { get; } = new(); public async Task3. Run and verify
```bash dotnet run # In the second terminal: conductor workflow create greetings.json conductor workflow start -w greetings -i '{"name":"Conductor"}' --sync # result: Hello Conductor ``` See the [C# SDK guide](../documentation/clientsdks/csharp-sdk.md) for the maintained examples and SDK reference.1. Create a Rust app and add the SDK
```bash cargo new greetings-worker cd greetings-worker ``` In `Cargo.toml`, add the SDK and async runtime under `[dependencies]`: ```toml [dependencies] conductor = { version = "0.1", package = "conductor-sdk", features = ["macros"] } conductor-macros = "0.1" tokio = { version = "1", features = ["full"] } ```2. Save the worker and workflow app
Replace `src/main.rs` with: ```rust use conductor::{ client::ConductorClient, configuration::Configuration, models::{StartWorkflowRequest, WorkflowDef, WorkflowTask}, worker::TaskHandler, }; use conductor_macros::worker; #[worker(name = "greet")] async fn greet(name: String) -> String { format!("Hello {}", name) } fn greetings_workflow() -> WorkflowDef { WorkflowDef::new("greetings") .with_version(1) .with_task( WorkflowTask::simple("greet", "greet_ref") .with_input_param("name", "${workflow.input.name}"), ) .with_output_param("result", "${greet_ref.output.result}") } #[tokio::main] async fn main() -> Result<(), Box3. Run and verify
```bash cargo run # result: Some("Hello Conductor") ``` See the maintained [Rust SDK quickstart](https://github.com/conductor-oss/rust-sdk#60-second-quickstart) for worker configuration, metrics, and production patterns.