Installation

Add the dependency to your pom.xml:

<dependency>
  <groupId>ai.autohand</groupId>
  <artifactId>agent-sdk-java</artifactId>
  <version>1.0.0-SNAPSHOT</version>
</dependency>

High-Level API

Agent

Agent agent = Agent.create(AgentOptions.builder()
    .cwd(".")
    .instructions("Be concise and helpful.")
    .build());

Run run = agent.send("Explain what this SDK does");
run.stream(event -> { ... });

Agent Methods

static Agent create(AgentOptions options)
Run send(String input)
Run run(String input)
<T> T runJson(String input, Class<T> clazz)
void close()

Run

void stream(Consumer<Event> handler)
RunResult wait()
void abort()

Low-Level API

AutohandSDK

AutohandSDK sdk = new AutohandSDK();
sdk.start();
sdk.streamPrompt(params, event -> { ... });

Key Methods

void start()
void stop()
void streamPrompt(PromptParams params, Consumer<Event> handler)
void allowPermission(String requestId, DecisionScope scope)
void denyPermission(String requestId, DecisionScope scope)
void setPermissionMode(String mode)
void setPlanMode(boolean enabled)
void setModel(String model)
void setSystemPrompt(String prompt)
void appendSystemPrompt(String prompt)
ContextUsage getContextUsage()
void addHook(HookDefinition hook)

CLI Runtime Control

Core lifecycle and auto-mode operations are available on Agent, AutohandSDK, and RPCClient. Use AutohandSDK or RPCClient for the complete approval, session, MCP, learning, tool-registry, and context surface.

  • Conversation and handoff: reset, createBrowserHandoff, attachBrowserHandoff, attachLatestBrowserHandoff
  • Auto-mode: startAutoMode, getAutoModeStatus, pauseAutoMode, resumeAutoMode, cancelAutoMode, getAutoModeLog
  • Approvals and sessions: acknowledgePermission, respondDirectoryAccess, acknowledgeDirectoryAccess, decideChanges, getHistory, getSession, attachSession
  • Integrations and context: setYoloMode, setYoloModeAlias, setVscodeMcpTools, respondMcpInvocation, recommendLearn, updateLearn, generateLearn, getToolsRegistry, setContextCompact

See Control the CLI runtime for behavior, safety contracts, object placement, and the equivalent names in every CLI-backed SDK.

Example Reference

Source-backed examples pulled from /agentsdk/tin-wrapper/java/examples.

Basic Usage

import ai.autohand.sdk.sdk.AutohandSDK;
import ai.autohand.sdk.types.*;

public class BasicUsage {
  public static void main(String[] args) throws Exception {
    AutohandSDK sdk = new AutohandSDK(new SDKConfig(
      System.getProperty("user.dir"),
      System.getenv("AUTOHAND_CLI_PATH"),
      false,
      300_000,
      null, null, null, null, null,
      null, null, null, null,
      null, null, null, null,
      null, null, null, null, null, null,
      null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null,
      null, null, null, null, null,
      null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null
    ));

    try {
      sdk.start();
      System.out.println("SDK started");
      sdk.streamPrompt(new PromptParams("Hello, Autohand!"), event -> {
        if (event instanceof Events.MessageUpdateEvent mue) {
          System.out.print(mue.delta());
        }
      });
      sdk.stop();
      System.out.println("SDK stopped");
    } catch (Exception e) {
      System.err.println("Error: " + e.getMessage());
      sdk.stop();
      System.exit(1);
    }
  }
}

Streaming Events

import ai.autohand.sdk.sdk.AutohandSDK;
import ai.autohand.sdk.types.*;

public class Streaming {
  public static void main(String[] args) throws Exception {
    AutohandSDK sdk = new AutohandSDK(new SDKConfig(
      System.getProperty("user.dir"),
      System.getenv("AUTOHAND_CLI_PATH"), true, 300_000,
      null, null, null, null, null,
      null, null, null, null,
      null, null, null, null,
      null, null, null, null, null, null,
      null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null,
      null, null, null, null, null,
      null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null
    ));

    try {
      sdk.start();
      sdk.streamPrompt(new PromptParams("Analyze the current directory structure"), event -> {
        if (event instanceof Events.MessageUpdateEvent e) {
          System.out.print(e.delta());
        }
      });
      sdk.stop();
    } catch (Exception e) {
      System.err.println("Error: " + e.getMessage());
      sdk.stop();
      System.exit(1);
    }
  }
}

Structured JSON

import ai.autohand.sdk.sdk.Agent;
import ai.autohand.sdk.sdk.AgentOptions;

import java.util.List;
import java.util.Map;

public class StructuredJson {
  public static void main(String[] args) throws Exception {
    Agent agent = Agent.create(AgentOptions.builder()
      .cwd(".")
      .build());

    try {
      var schema = Map.of(
        "summary", "string",
        "risks", List.of(Map.of("title", "string", "severity", "low | medium | high"))
      );

      var risk = agent.runJson(
        "Assess the publish readiness of this codebase.",
        String.class,
        "ReleaseRisk",
        schema,
        null
      );

      System.out.println(risk);
    } finally {
      agent.close();
    }
  }
}

Permissions Demo

import ai.autohand.sdk.sdk.AutohandSDK;
import ai.autohand.sdk.types.*;

public class PermissionsDemo {
  public static void main(String[] args) throws Exception {
    String cliPath = System.getenv("AUTOHAND_CLI_PATH");
    AutohandSDK sdk = new AutohandSDK(new SDKConfig(
      System.getProperty("user.dir"),
      cliPath, false, 300_000,
      null, null, null, null, null,
      null, null, null, null,
      null, null, null, null,
      null, null, null, null, null, null,
      null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null,
      null, null, null, null, null,
      null, null, null, null, null, null, null,
      null, null, null, null, null, null, null, null
    ));

    sdk.start();
    sdk.setPermissionMode(PermissionMode.INTERACTIVE);
    sdk.streamPrompt(new PromptParams("List files"), event -> {
      if (event instanceof Events.PermissionRequestEvent req) {
        sdk.allowPermission(req.requestId(), DecisionScope.ONCE);
      } else if (event instanceof Events.ToolEndEvent toolEnd) {
        System.out.println("tool=" + toolEnd.toolName());
      }
    });
    sdk.stop();
  }
}

Events

Events are delivered through a Consumer<Event> callback. Key types:

  • MessageUpdateEvent - Streaming assistant text delta
  • ToolStartEvent - Tool execution started
  • ToolEndEvent - Tool execution completed
  • PermissionRequestEvent - Runtime pause for approval
  • automode_iteration, automode_complete, and automode_error - Auto-mode lifecycle
  • ErrorEvent - Error occurred

See Hooks and events for the complete normalized event contract.

Error Handling

The SDK uses structured exceptions:

try {
    sdk.start();
} catch (IOException e) { ... }

try {
    var result = agent.runJson("Return JSON", MyClass.class);
} catch (StructuredOutputError e) {
    System.err.println("Invalid JSON: " + e.getMessage());
    System.err.println("Raw: " + e.rawResponse());
}

See Also