AgentClient control-plane reference

July 20, 2026 · View on GitHub

AgentClient (io.orkes.conductor.client.AgentClient, in the conductor-client module) is the Java SDK's interface to the agent control-plane (/api/agent/*). Standard Conductor endpoints (/api/workflow/*, /api/tasks, etc.) remain on the SDK's typed clients (WorkflowClient, TaskClient, MetadataClient). Obtain an agent client with new OrkesClients(conductorClient).getAgentClient() or construct OrkesAgentClient directly.

Every request goes through the shared ConductorClient's native HTTP + auth + serialization layer. No hand-rolled HTTP. ConductorClientException is mapped to the typed AgentAPIException / AgentNotFoundException (io.orkes.conductor.client.exceptions).

Methods

MethodHTTPJava input typeJava return typeDescription
compileAgentPOST /api/agent/compileAgentRequestCompileResponseCompile to Conductor workflow def — no side effects
deployAgentPOST /api/agent/deployAgentRequestStartResponseRegister workflow def without starting
startAgentPOST /api/agent/startAgentRequestStartResponseCompile + register + start execution
getAgentStatusGET /api/agent/{id}/statuspath: executionIdAgentStatusResponsePoll execution status; includes HITL pending-tool
getExecutionGET /api/agent/execution/{id}path: executionIdMap<String,Object>Fetch the full execution tree
listExecutionsGET /api/agent/executionsquery parameter mapMap<String,Object>Search agent executions
respondPOST /api/agent/{id}/respondRespondBodyvoidResume a paused HITL task
cancelAgentDELETE /api/agent/{id}/cancelpath: executionId; optional reason queryvoidImmediately cancel/terminate an execution
stopAgentPOST /api/agent/{id}/stoppath: executionIdvoidGracefully stop after the current iteration
signalAgentPOST /api/agent/{id}/signalpath: executionId; message bodyvoidInject persistent context
streamSseGET /api/agent/stream/{id}path: executionId; optional last event IDSseClientOpen the resumable SSE event stream

AgentRequest

Input to compileAgent, deployAgent, and startAgent (io.orkes.conductor.client.model.agent.AgentRequest). A pure transport DTO: the agent definition arrives pre-serialized as a JSON-ready map — domain serialization is owned by conductor-client-ai (AgentRuntime.agentRequest(agent) calls AgentConfigSerializer.serialize(agent) and resolves the Framework discriminator before building the request).

// Already-deployed agent — version is optional
AgentRequest.deployedAgent("researcher", 3)
    .prompt("Summarize the release risks")
    .build()

// Native agent — AgentRuntime passes the serialized agent map
AgentRequest.nativeAgent(serializedAgent).build()

// Framework-backed agent — framework wire name + serialized raw config
AgentRequest.frameworkAgent("openai", serializedAgent).build()
AgentRequest.frameworkAgent("langchain", serializedAgent).build()

// Framework skill reference instead of rawConfig
AgentRequest.frameworkAgent("skill", null)
    .model("anthropic/claude-sonnet-4-6")
    .skillRef(Map.of("name", "code-review", "version", 2))
    .build()

// With execution fields (for /start only)
AgentRequest.nativeAgent(serializedAgent)
    .prompt("What is the capital of France?")
    .sessionId("session-abc")
    .runId("a1b2c3...")           // per-execution domain UUID for stateful agents
    .staticPlan(plan.toJson())    // pre-serialized map, written as "static_plan"
    .idempotencyKey("question-123")
    .build()

Wire output (mutually exclusive shapes, fixed at build time):

FactoryJSON emitted
deployedAgent(name, version)"name": name, "version": version (version omitted when null)
nativeAgent(config)"agentConfig": config
frameworkAgent(framework, config)"framework": framework, "rawConfig": config
frameworkAgent(framework, null).skillRef(ref)"framework": framework, "skillRef": ref

Field mapping to server StartRequest:

AgentRequest fieldJava typeJSON keyServer StartRequest fieldUsed by
nameString"name"namedeployed agents
versionInteger"version"versiondeployed agents (optional)
agentConfigObject (map)"agentConfig" (native path)agentConfignative agents
frameworkString"framework" (framework path)frameworkframework agents
rawConfigObject (map)"rawConfig" (framework path)rawConfigframework agents
modelString"model"modeloptional model override
skillRefMap<String,Object>"skillRef"skillRefframework skill agents
promptString"prompt"promptstart only
sessionIdString"sessionId"sessionIdstart (stateful)
runIdString"runId"runIdstart (stateful isolation)
staticPlanObject (map)"static_plan" (AgentRuntime calls plan.toJson())staticPlan (@JsonProperty("static_plan"))start (PLAN_EXECUTE)
mediaList<String>"media"mediastart (multi-modal)
contextMap<String,Object>"context"contextstart
idempotencyKeyString"idempotencyKey"idempotencyKeystart
credentialsList<String>"credentials"credentialscompile / start
timeoutSecondsInteger"timeoutSeconds"timeoutSecondscompile / start

Null fields are never written — the class is annotated @JsonInclude(NON_NULL). The three request forms are mutually exclusive: use deployed name/version, inline native agentConfig, or framework framework plus rawConfig/skillRef.

Framework wire values:

Enum constantWire value
Framework.OPENAI"openai"
Framework.GOOGLE_ADK"google_adk"
Framework.LANGCHAIN"langchain"
Framework.LANGGRAPH"langgraph"
Framework.SKILL"skill"
Framework.VERCEL_AI"vercel_ai"
Framework.CLAUDE_AGENT_SDK"claude_agent_sdk"

AgentRuntime resolves agent.getFramework()Framework via Framework.of(String) (returns Optional.empty() for unrecognised strings, routing them through the native path).

staticPlan is serialized as "static_plan".


RespondBody

Input to respond. Provides factory methods for the three common patterns; arbitrary extra fields are flattened to the top level via @JsonAnyGetter.

RespondBody.approve()                  // { "approved": true }
RespondBody.approve("Looks good")      // { "approved": true, "reason": "Looks good" }
RespondBody.reject("Needs review")     // { "approved": false, "reason": "Needs review" }
RespondBody.of(Map.of("selected", "writer"))  // { "selected": "writer" }  ← MANUAL strategy

Used by AgentHandle:

AgentHandle methodRespondBody factoryWire JSON
handle.approve()RespondBody.approve(){ "approved": true }
handle.approve(comment)RespondBody.approve(comment){ "approved": true, "reason": "..." }
handle.reject(reason)RespondBody.reject(reason){ "approved": false, "reason": "..." }
handle.respond(map)RespondBody.of(map)the map at the top level

compileAgent

Compile an agent into a Conductor workflow definition. No workflow is registered or executed.

Used by AgentRuntime.plan(agent).

HTTP: POST /api/agent/compile

Request body — AgentRequest

// AgentRuntime builds this via agentRequest(agent), serializing the agent first:
AgentRequest.nativeAgent(AGENT_SERIALIZER.serialize(agent)).build()
// or, for framework agents — the resolved framework's wire name:
AgentRequest.frameworkAgent(fw.wireValue(), AGENT_SERIALIZER.serialize(agent)).build()

Native agent wire shape (the map produced by AgentConfigSerializer.serialize(agent)):

{ "agentConfig": { "name": "my_agent", "model": "anthropic/claude-sonnet-4-6", "strategy": "handoff", ... } }

Framework agent wire shape:

{ "framework": "openai", "rawConfig": { "name": "my_agent", "model": "anthropic/claude-sonnet-4-6", "tools": [...] } }

Response — CompileResponse

{ "workflowDef": { "name": "my_agent", "version": 1, "tasks": [...] }, "requiredWorkers": ["my_tool_a"] }
FieldGetterTypeDescription
workflowDefgetWorkflowDef()Map<String,Object>Full Conductor workflow definition.
requiredWorkersgetRequiredWorkers()List<String>Task type names the SDK must register local workers for.

How the SDK uses it: AgentRuntime.plan(agent) returns the CompileResponse directly.


deployAgent

Compile and register the workflow definition on the server without starting an execution. Idempotent.

Used by AgentRuntime.deploy(Agent...).

HTTP: POST /api/agent/deploy

Request body — AgentRequest

Same as compileAgent — agent definition only, no prompt.

Response — StartResponse

{ "agentName": "my_agent", "requiredWorkers": ["my_tool_a"] }
FieldGetterTypeDescription
agentNamegetAgentName()StringThe registered workflow name on the server.
requiredWorkersgetRequiredWorkers()List<String>Task type names the SDK must have workers running for.
executionIdgetExecutionId()StringAlways null for deploy — no execution was started.

How the SDK uses it: AgentRuntime.deploy() reads resp.getAgentName() and wraps it in DeploymentInfo.


startAgent

Compile, register, and start a workflow execution in one call.

Used by AgentRuntime.startAsync(agent, prompt, plan).

HTTP: POST /api/agent/start

Request body — AgentRequest

Start an already-deployed agent without resending its definition:

StartResponse response = client.startAgent(
    AgentRequest.deployedAgent("researcher", 3)
        .prompt("What changed in the latest release?")
        .build());
{
  "name": "researcher",
  "version": 3,
  "prompt": "What changed in the latest release?"
}

Inline definitions remain supported:

{
  "agentConfig": { ... },
  "prompt": "What is the capital of France?",
  "sessionId": "session-abc",
  "runId": "a1b2c3d4e5f6...",
  "static_plan": { "steps": [...] },
  "idempotencyKey": "question-123"
}

The idempotency key is optional. Callers that retry the same logical start should reuse the same stable value; the client does not generate one.

Response — StartResponse

{ "executionId": "a3f92b1c-8e4d-4b7a-9c2e-1d5f3a8e6b02", "agentName": "my_agent", "requiredWorkers": ["my_tool_a"] }
FieldGetterTypeDescription
executionIdgetExecutionId()StringConductor workflow ID. @JsonAlias handles legacy keys (workflowId, id, correlationId).
agentNamegetAgentName()StringThe registered workflow name.
requiredWorkersgetRequiredWorkers()List<String>Task type names the SDK must have workers polling before the agent can progress.

How the SDK uses it: AgentRuntime.startAsync() reads response.getExecutionId() and passes it to new AgentHandle(executionId, agentClient, workflowClient).


getAgentStatus

Poll the current status of a running or completed execution.

Used by AgentHandle.waitForResult() and AgentHandle.waitUntilWaiting().

HTTP: GET /api/agent/{executionId}/status

Response — AgentStatusResponse

{ "executionId": "...", "status": "COMPLETED", "startTime": 1710000000000, "endTime": 1710000005000, "isComplete": true, "isRunning": false, "output": { ... } }

HITL paused:

{ "status": "RUNNING", "isWaiting": true, "pendingTool": { "taskRefName": "...", "tool_name": "...", "parameters": { ... } } }

AgentStatusResponse fields:

JSON fieldGetterTypeSourceDescription
executionIdgetExecutionId()Stringpath param
statusgetStatus()Stringworkflow.getStatus().name()RUNNING, COMPLETED, FAILED, TERMINATED, TIMED_OUT, PAUSED
startTimegetStartTime()Longworkflow start timestampEpoch milliseconds; nullable until supplied by the server
endTimegetEndTime()Longworkflow end timestampEpoch milliseconds; nullable while execution is active
isCompleteisComplete()booleanworkflow.getStatus().isTerminal()true for all terminal statuses
isRunningisRunning()booleanstatus == RUNNING
outputgetOutput()Map<String,Object>workflow.getOutput()Only present when isComplete() == true
reasonForIncompletiongetReasonForIncompletion()Stringworkflow.getReasonForIncompletion()Only present on non-COMPLETED terminal status
isWaitingisWaiting()booleanHUMAN task IN_PROGRESStrue when a HITL task is paused
pendingToolgetPendingTool()PendingToolHUMAN task inputDataOnly when isWaiting() == true

PendingTool fields:

JSON fieldGetterTypeDescription
taskRefNamegetTaskRefName()StringConductor task reference name.
tool_namegetToolName()StringLogical tool name shown to the human.
parametersgetParameters()Map<String,Object>Args the agent passed to the tool.
response_schemagetResponseSchema()ObjectJSON Schema the response must conform to (optional).
response_ui_schemagetResponseUiSchema()ObjectUI rendering hints (optional).

respond

Resume a paused HITL execution.

Used by AgentHandle.approve(), .reject(), .respond(Map) and AgentStream.approve(), .reject().

HTTP: POST /api/agent/{executionId}/respond

Request body — RespondBody

{ "approved": true }
{ "approved": false, "reason": "Needs review" }
{ "selected": "writer" }

Response

void — returns nothing. Throws AgentAPIException if no pending HUMAN task exists.


cancelAgent

Immediately cancel an agent execution. This is distinct from graceful stopping: cancellation terminates now and may record an operator reason.

client.cancelAgent(executionId, "Superseded by a newer request");

HTTP: DELETE /api/agent/{executionId}/cancel?reason=Superseded%20by%20a%20newer%20request

The reason query parameter is omitted when the Java argument is null, empty, or blank. HTTP 404 maps to AgentNotFoundException; other HTTP failures map to AgentAPIException through the normal client transport.


stopAgent

Request a graceful deterministic stop after the current agent iteration finishes. Unlike cancellation, this preserves the current iteration and does not take a reason.

client.stopAgent(executionId);

HTTP: POST /api/agent/{executionId}/stop

Use stopAgent when the current iteration should finish cleanly; use cancelAgent when work must terminate immediately.


signalAgent

Inject a durable text message into a running agent's context. This is an agent-control-plane signal, not a response to a pending human approval; use respond for a HUMAN task.

Fragment — obtain client as shown in the control-plane overview.

client.signalAgent(executionId, "Customer supplied order number 12345");

HTTP: POST /api/agent/{executionId}/signal

The body is the message accepted by the agent control plane. The method returns void; AgentNotFoundException represents a missing execution and AgentAPIException represents another server failure. Do not put credentials or sensitive raw customer data in a signal.


streamSse

Open the resumable server-sent event stream for an agent execution. AgentRuntime.stream(...) uses this method; direct users must close the returned SseClient.

Fragment — obtain client as shown in the control-plane overview.

import java.util.Map;

try (SseClient stream = client.streamSse(executionId, null)) {
    Map<String, Object> event;
    while ((event = stream.nextEvent()) != null) {
        System.out.println(event);
    }
}

HTTP: GET /api/agent/stream/{executionId}

Pass the last received event ID as the second argument to resume after a reconnect. The client reconnects mid-stream with Last-Event-ID; if the server rejects streaming altogether it throws SSEUnavailableException. Fall back to getAgentStatus polling in that case. Treat streamed content as potentially sensitive and redact it before logging.


WorkflowClient usage

Raw workflow data (GET /api/workflow/{id}) is fetched via the standard Conductor WorkflowClient — not AgentClient. AgentClient owns only /api/agent/*.

WorkflowClient.getWorkflow(id, true) is called inside AgentHandle.buildResult() once, after getAgentStatus returns terminal, to walk the typed Workflow/Task objects and compute:

  • Token usageLLM_CHAT_COMPLETE task outputData: promptTokens, completionTokens, tokenUsedAgentResult.getTokenUsage()
  • Tool calls — worker tasks whose referenceTaskName starts with call_AgentResult.getToolCalls()

Fires automatically inside run() / waitForResult(). Callers never invoke it directly.


AgentConfig (request field)

The agent definition serialized under the agentConfig key by AgentConfigSerializer.

FieldTypeDescription
nameStringAgent/workflow name.
modelString"provider/model" e.g. "anthropic/claude-sonnet-4-6".
instructionsString | ObjectSystem prompt or PromptTemplateRef.
toolsList<ToolConfig>Tool definitions.
agentsList<AgentConfig>Sub-agents (for multi-agent strategies).
strategyString"handoff" (default), "sequential", "parallel", "router", "swarm", "round_robin", "random", "plan_execute", "manual".
routerAgentConfig | WorkerRefFor "router" strategy.
guardrailsList<GuardrailConfig>Input/output guardrails.
maxTurnsintDefault 100.
maxTokensIntegerLLM max_tokens.
temperatureDoubleLLM temperature.
timeoutSecondsintExecution timeout.
credentialsList<String>Credential names injected at runtime.
outputTypeOutputTypeConfigStructured output definition.
terminationTerminationConfigEarly termination condition.
handoffsList<HandoffConfig>Swarm handoff triggers.
callbacksList<CallbackConfig>Before/after model callbacks.
codeExecutionCodeExecutionConfigLocal code execution settings.
cliConfigCliConfigCLI command execution settings.
plannerAgentConfigPLAN_EXECUTE: agent that produces the plan.
fallbackAgentConfigPLAN_EXECUTE: agent used when the plan fails.
plannerContextList<Map>PLAN_EXECUTE: text/URL context appended to the planner's prompt.
synthesizeBooleanAppend a synthesis step after parallel sub-agents.
includeContentsString"none" = fresh context; absent = inherit parent context.
baseUrlStringPer-agent LLM provider base URL override.
metadataMap<String,Object>Arbitrary metadata stored with the workflow definition.
frameworkStringFramework ID — set by SDK bridges, not by callers directly.

ToolConfig

FieldTypeDefaultDescription
nameStringTool name shown to the LLM.
descriptionStringTool description.
inputSchemaMap<String,Object>JSON Schema for tool parameters.
outputSchemaMap<String,Object>JSON Schema for tool return value.
toolTypeString"worker""worker", "http", "mcp", "human", "generate_image", "generate_audio", "generate_pdf", "rag_search", "pull_workflow_messages".
approvalRequiredbooleanfalsePause for human approval before executing.
timeoutSecondsIntegerPer-tool execution timeout.
maxCallsIntegerMaximum invocations per run.
configMap<String,Object>Type-specific config: url/method/headers for HTTP; server_url for MCP.
guardrailsList<GuardrailConfig>Tool-level guardrails.
statefulbooleanfalseRegister worker under a per-execution domain (prevents cross-instance task stealing).