packages/sdk-java/qwencode/README.md
The Qwen Code Java SDK is a minimum experimental SDK for programmatic access to Qwen Code functionality. It provides a Java interface to interact with the Qwen Code CLI, allowing developers to integrate Qwen Code capabilities into their Java applications.
Add the following dependency to your Maven pom.xml:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>qwencode-sdk</artifactId>
<version>{$version}</version>
</dependency>
Or if using Gradle, add to your build.gradle:
implementation 'com.alibaba:qwencode-sdk:{$version}'
# Compile the project
mvn compile
# Run tests
mvn test
# Package the JAR
mvn package
# Install to local repository
mvn install
The simplest way to use the SDK is through the QwenCodeCli.simpleQuery() method:
public static void runSimpleExample() {
List<String> result = QwenCodeCli.simpleQuery("hello world");
result.forEach(logger::info);
}
For more advanced usage with custom transport options:
public static void runTransportOptionsExample() {
TransportOptions options = new TransportOptions()
.setModel("qwen3-coder-flash")
.setPermissionMode(PermissionMode.AUTO_EDIT)
.setCwd("./")
.setEnv(new HashMap<String, String>() {{put("CUSTOM_VAR", "value");}})
.setIncludePartialMessages(true)
.setTurnTimeout(new Timeout(120L, TimeUnit.SECONDS))
.setMessageTimeout(new Timeout(90L, TimeUnit.SECONDS))
.setAllowedTools(Arrays.asList("read_file", "write_file", "list_directory"));
List<String> result = QwenCodeCli.simpleQuery("who are you, what are your capabilities?", options);
result.forEach(logger::info);
}
For streaming content handling with custom content consumers:
public static void runStreamingExample() {
QwenCodeCli.simpleQuery("who are you, what are your capabilities?",
new TransportOptions().setMessageTimeout(new Timeout(10L, TimeUnit.SECONDS)), new AssistantContentSimpleConsumers() {
@Override
public void onText(Session session, TextAssistantContent textAssistantContent) {
logger.info("Text content received: {}", textAssistantContent.getText());
}
@Override
public void onThinking(Session session, ThinkingAssistantContent thinkingAssistantContent) {
logger.info("Thinking content received: {}", thinkingAssistantContent.getThinking());
}
@Override
public void onToolUse(Session session, ToolUseAssistantContent toolUseContent) {
logger.info("Tool use content received: {} with arguments: {}",
toolUseContent, toolUseContent.getInput());
}
@Override
public void onToolResult(Session session, ToolResultAssistantContent toolResultContent) {
logger.info("Tool result content received: {}", toolResultContent.getContent());
}
@Override
public void onOtherContent(Session session, AssistantContent<?> other) {
logger.info("Other content received: {}", other);
}
@Override
public void onUsage(Session session, AssistantUsage assistantUsage) {
logger.info("Usage information received: Input tokens: {}, Output tokens: {}",
assistantUsage.getUsage().getInputTokens(), assistantUsage.getUsage().getOutputTokens());
}
}.setDefaultPermissionOperation(Operation.allow));
logger.info("Streaming example completed.");
}
other examples see src/test/java/com/alibaba/qwen/code/cli/example
The SDK follows a layered architecture:
QwenCodeCli class with simple static methods for basic usageSession classProcessTransport)The SDK supports different permission modes for controlling tool execution:
default: Write tools are denied unless approved via canUseTool callback or in allowedTools. Read-only tools execute without confirmation.plan: Blocks all write tools, instructing AI to present a plan first.auto-edit: Auto-approve edit tools (edit, write_file) while other tools require confirmation.yolo: All tools execute automatically without confirmation.The SDK provides two key interfaces for handling events and content from the CLI:
The SessionEventConsumers interface provides callbacks for different types of messages during a session:
onSystemMessage: Handles system messages from the CLI (receives Session and SDKSystemMessage)onResultMessage: Handles result messages from the CLI (receives Session and SDKResultMessage)onAssistantMessage: Handles assistant messages (AI responses) (receives Session and SDKAssistantMessage)onPartialAssistantMessage: Handles partial assistant messages during streaming (receives Session and SDKPartialAssistantMessage)onUserMessage: Handles user messages (receives Session and SDKUserMessage)onOtherMessage: Handles other types of messages (receives Session and String message)onControlResponse: Handles control responses (receives Session and CLIControlResponse)onControlRequest: Handles control requests (receives Session and CLIControlRequest, returns CLIControlResponse)onPermissionRequest: Handles permission requests (receives Session and CLIControlRequest<CLIControlPermissionRequest>, returns Behavior)The AssistantContentConsumers interface handles different types of content within assistant messages:
onText: Handles text content (receives Session and TextAssistantContent)onThinking: Handles thinking content (receives Session and ThinkingAssistantContent)onToolUse: Handles tool use content (receives Session and ToolUseAssistantContent)onToolResult: Handles tool result content (receives Session and ToolResultAssistantContent)onOtherContent: Handles other content types (receives Session and AssistantContent)onUsage: Handles usage information (receives Session and AssistantUsage)onPermissionRequest: Handles permission requests (receives Session and CLIControlPermissionRequest, returns Behavior)onOtherControlRequest: Handles other control requests (receives Session and ControlRequestPayload, returns ControlResponsePayload)Important Note on Event Hierarchy:
SessionEventConsumers is the high-level event processor that handles different message types (system, assistant, user, etc.)AssistantContentConsumers is the low-level content processor that handles different types of content within assistant messages (text, tools, thinking, etc.)Processor Relationship:
SessionEventConsumers → AssistantContentConsumers (SessionEventConsumers uses AssistantContentConsumers to process content within assistant messages)Event Derivation Relationships:
onAssistantMessage → onText, onThinking, onToolUse, onToolResult, onOtherContent, onUsageonPartialAssistantMessage → onText, onThinking, onToolUse, onToolResult, onOtherContentonControlRequest → onPermissionRequest, onOtherControlRequestEvent Timeout Relationships:
Each event handler method has a corresponding timeout method that allows customizing the timeout behavior for that specific event:
onSystemMessage ↔ onSystemMessageTimeoutonResultMessage ↔ onResultMessageTimeoutonAssistantMessage ↔ onAssistantMessageTimeoutonPartialAssistantMessage ↔ onPartialAssistantMessageTimeoutonUserMessage ↔ onUserMessageTimeoutonOtherMessage ↔ onOtherMessageTimeoutonControlResponse ↔ onControlResponseTimeoutonControlRequest ↔ onControlRequestTimeoutFor AssistantContentConsumers timeout methods:
onText ↔ onTextTimeoutonThinking ↔ onThinkingTimeoutonToolUse ↔ onToolUseTimeoutonToolResult ↔ onToolResultTimeoutonOtherContent ↔ onOtherContentTimeoutonPermissionRequest ↔ onPermissionRequestTimeoutonOtherControlRequest ↔ onOtherControlRequestTimeoutDefault Timeout Values:
SessionEventSimpleConsumers default timeout: 180 seconds (Timeout.TIMEOUT_180_SECONDS)AssistantContentSimpleConsumers default timeout: 60 seconds (Timeout.TIMEOUT_60_SECONDS)Timeout Hierarchy Requirements:
For proper operation, the following timeout relationships should be maintained:
onAssistantMessageTimeout return value should be greater than onTextTimeout, onThinkingTimeout, onToolUseTimeout, onToolResultTimeout, and onOtherContentTimeout return valuesonControlRequestTimeout return value should be greater than onPermissionRequestTimeout and onOtherControlRequestTimeout return valuesThe TransportOptions class allows configuration of how the SDK communicates with the Qwen Code CLI:
pathToQwenExecutable: Path to the Qwen Code CLI executablecwd: Working directory for the CLI processmodel: AI model to use for the sessionpermissionMode: Permission mode that controls tool executionenv: Environment variables to pass to the CLI processmaxSessionTurns: Limits the number of conversation turns in a sessioncoreTools: List of core tools that should be available to the AIexcludeTools: List of tools to exclude from being available to the AIallowedTools: List of tools that are pre-approved for use without additional confirmationauthType: Authentication type to use for the sessionincludePartialMessages: Enables receiving partial messages during streaming responsesturnTimeout: Timeout for a complete turn of conversationmessageTimeout: Timeout for individual messages within a turnresumeSessionId: ID of a previous session to resumeotherOptions: Additional command-line options to pass to the CLIQwenCodeCli.newSession() to create a new session with custom optionsSession class provides methods to send prompts, handle responses, and manage session statesession.close() to properly terminate the CLI processsetResumeSessionId() in TransportOptions to resume a previous sessionsession.interrupt() to interrupt a currently running promptsession.setModel() to change the model during a sessionsession.setPermissionMode() to change the permission mode during a sessionThe SDK uses a thread pool for managing concurrent operations with the following default configuration:
The SDK provides specific exception types for different error scenarios:
SessionControlException: Thrown when there's an issue with session control (creation, initialization, etc.)SessionSendPromptException: Thrown when there's an issue sending a prompt or receiving a responseSessionClosedException: Thrown when attempting to use a closed sessionA: The SDK requires Java 1.8 or higher.
A: The SDK includes timeout utilities. You can configure timeouts using the Timeout class in TransportOptions.
A: This is likely due to permission modes. Check your permission mode settings and consider using allowedTools to pre-approve certain tools.
A: Use the setResumeSessionId() method in TransportOptions to resume a previous session.
A: Yes, use the setEnv() method in TransportOptions to pass environment variables to the CLI process.
Apache-2.0 - see LICENSE for details.