Qoder Agent SDK ships in three languages: TypeScript, Python, and Java. All three use the same CLI runtime protocol and share the core capabilities: the agent loop, tools, permissions, hooks, sessions, and MCP. API signatures, type definitions, and naming follow each language's conventions (camelCase in TypeScript and Java; snake_case for public options in Python). TypeScript and Python cover nearly the same surface; Java's surface is narrower, and some options exist in only one or two languages. See Language differences below. The full API references are maintained per language:
Most TypeScript and Python options map one-to-one, and Java lacks some of them. The differences are listed below. Each language reference page remains authoritative for its own surface.
Python does not have the following capabilities.
The following capabilities are available in TypeScript or Python, but Java has no corresponding option or method.
All three languages have the following capabilities, but Java behaves differently:
Core API mapping across the three SDKs, handy for cross-language migration:
Feature pages carry merged examples for each language; switch TypeScript / Python / Java inside any code block. Sections without a Java equivalent mark the applicable languages in the heading or at the top of the page:
By language
| Language | Reference | Package |
|---|---|---|
| TypeScript | SDK References - TypeScript | @qoder-ai/qoder-agent-sdk |
| Python | SDK References - Python | qoder-agent-sdk |
| Java | SDK References - Java | com.qoder.sdk:qoder-agent-sdk |
Language differences
Most TypeScript and Python options map one-to-one, and Java lacks some of them. The differences are listed below. Each language reference page remains authoritative for its own surface.
TypeScript only
| Capability | Option or method | Notes |
|---|---|---|
| Built-in tool behavior | toolConfig | Tune how built-in tools behave; see Tools |
| Session persistence control | persistSession, resumeSessionAt, resumeDropsTurn | Fine-grained control over what a resumed session loads and keeps |
| Prompt suggestions | promptSuggestions | Receive suggested follow-up prompts |
| Goal maximum turns | goalMaxTurns, setGoalMaxTurns() | Configure future Goals without changing the current Goal; see the TypeScript reference |
| Model request patches | modelRequestPatches | Adjust outgoing model requests |
| Custom transport and process control | transport, spawnQoderCLIProcess, executable, executableArgs | Replace how the runtime is launched or connected |
Python only
| Capability | Option | Notes |
|---|---|---|
| System prompt from a file | system_prompt={"type": "file", "path": ...} | See Load the prompt from a file |
| MCP authentication callback | on_mcp_oauth_required | Inbound callback when a server requires OAuth; TypeScript drives this through runtime methods instead |
| MCP status callback | on_mcp_status_change | Inbound callback for server status transitions |
| Read buffer limit | max_buffer_size | Cap the transport read buffer |
TypeScript and Java
Python does not have the following capabilities.
| Capability | TypeScript | Java | Notes |
|---|---|---|---|
| Hook events in the message stream | includeHookEvents | includeHookEvents(boolean) | Deliver hook lifecycle events in the message stream; does not affect hook callbacks themselves |
Not yet available in Java
The following capabilities are available in TypeScript or Python, but Java has no corresponding option or method.
| Capability | TypeScript / Python entry point | Java |
|---|---|---|
| Subagent definitions | agents | No corresponding option; see Subagents |
| Plugins | plugins | No plugins option; reloadPlugins() does not return the plugin list; see Plugins |
| Skills and setting sources | skills, settingSources | Supports only selecting skills for a single message and reloadSkills() |
| Code security scans | securityScan / security_scan | No corresponding option; see Scan code for security issues |
| Usage and context queries | getContextUsage(), getUsageInfo(), and others | Only ResultMessage.usage(), which gives the turn's input and output token counts; see Cost and usage |
| Settings and output styles | settings, output style settings | See Use settings to provide permission rules and Adjust the output style separately |
| In-session permission updates | PermissionUpdate | Use PermissionResult.allow().withScope(PermissionScope.SESSION); see Approval options and scope (Java) |
| External authorization tool, MCP Tool Policy | permissionPromptToolName, MCP Tool Policy | See Permissions |
| Additional directories at startup | additionalDirectories / add_dirs | No startup option; after the session opens, call QoderSession.addDirectories(List<Path>). See Additional directories |
| AskUserQuestion | Handle AskUserQuestion in canUseTool | See Handle AskUserQuestion |
| Authentication failure callback | onAuthExpired / on_auth_expired | Catch AuthenticationException with error code CLI_AUTH_FATAL; see Authentication failure callback |
| Custom tool helpers | tool(), createSdkMcpServer() | Implement InProcessMcpHandler; see MCP integration |
| Strict MCP configuration | strictMcpConfig / strict_mcp_config | No corresponding option |
| Switching models at runtime | Switch the current model in fixed-model mode | No corresponding method; see Model selection |
| Specifying a new session ID | sessionId | The CLI assigns the session ID; read it from initialization(); see Session control |
| Read timeout and write policy for external session storage | loadTimeoutMs, sessionStoreFlush | Set mirroring batch and wait limits with sessionMirrorOptions(...); see External session storage |
| Renaming, tagging, and importing sessions | renameSession() and related functions | No corresponding functions |
| stderr callback | stderr | When the CLI exits abnormally, read the stderr tail with CliProcessException.getStderrTail() |
Java behavior differences
All three languages have the following capabilities, but Java behaves differently:
- CLI runtime: The Java SDK does not bundle the CLI. On first start it downloads the CLI version pinned to this release and caches it for reuse; see Managed CLI (Java).
- Authentication: Authentication is configured on
QoderClient.Builder.auth(), and every session created by the same client shares it.Auth.accessTokenEnv()reads only the JVM process environment, not variables passed throughputEnvironment(). - Subprocess environment: The CLI subprocess inherits only
PATHby default; pass other variables explicitly; see Subprocess environment (Java). - Tool list:
tools(empty list)is the same as not setting it and leaves the choice to the CLI default; an empty list cannot disable all tools; see Tools. - Input priority: The default
UserInputpriority isNOW; see Input modes. - Runtime controls: Runtime methods such as switching permission modes, MCP management, and rewind exist only on
QoderSession; the one-shotQoderQuerydoes not have them. - External session storage: If the external record is missing on resume, startup fails instead of falling back to the CLI's local storage; see External session storage.
- Model selection callback timeout: Not delivered to the application as an exception; detect it with a diagnostics listener; see SDK exceptions.
Naming map
Core API mapping across the three SDKs, handy for cross-language migration:
| Capability | TypeScript | Python | Java |
|---|---|---|---|
| One-shot query | query() | query() | QoderClient.query() |
| Streaming input | query() + async message stream | QoderSDKClient | QoderClient.openSession() + QoderSession.send() |
| Session options | Options (query({ options })) | QoderAgentOptions | SessionOptions (SessionOptions.builder()) |
| Auth: PAT from env | accessTokenFromEnv() | access_token_from_env() | Auth.accessTokenEnv() |
| Auth: PAT directly | accessToken() | access_token() | Auth.accessToken(SecretValue) |
| Auth: Service Account | serviceAccount() | service_account() | Auth.serviceAccountKey() / Auth.serviceAccountTokenProvider() |
| Auth: local login state | qodercliAuth() | qodercli_auth() | Auth.qoderCli() |
| Custom tools | tool() | @tool() decorator | Implement tools/list and tools/call in an InProcessMcpHandler |
| In-process MCP server | createSdkMcpServer() | create_sdk_mcp_server() | McpServerConfig.inProcess() |
| Permission callback | canUseTool | can_use_tool | canUseTool(ToolPermissionHandler) |
| Interrupt the current response | q.interrupt() | client.interrupt() | query.interrupt() / session.interrupt() |
| File rewind | q.rewindFiles() | client.rewind_files() | session.rewindFiles() |
| MCP status query | q.mcpServerStatus() | client.get_mcp_status() | session.mcpServerStatus() |
| Initialization result | q.initializationResult() | client.get_server_info() | initialization() |
| Context usage | q.getContextUsage() | client.get_context_usage() | — |
| Account and session usage | q.getUsageInfo() | client.get_usage_info() | — |
Note: Python's protocol-level structures—AgentDefinition, hooks outputs, settings, etc.—keep the wire-protocol camelCase field names (such asmaxTurns,hookSpecificOutput), unlike the snake_case public options. See each feature page for details.