Autohand Code Agent SDK
Embed the Autohand Code runtime inside your own products, tools, and workflows. The SDK gives you the same agent loop that started in the CLI, with structured events and approvals your app can own.
What's new in TypeScript
Development update — 6 September 2026. These improvements are verified in local TypeScript SDK builds; this is not a package release announcement or a claim of parity across every language SDK.
- Responsive cancellation: abort a run while an async stop condition is pending, then continue the same session. Read the cancellation contract.
- Typed rate-limit events: inspect provider, model, HTTP status, and retry timing without automatically retrying a rate-limited session. Handle rate limits.
- Verified packaged runtime: refreshed bundled CLI targets and an installed-package check covering stop/resume, cancellation, and HTTP 429. Check runtime compatibility.
Why we built this
Autohand Code started in the CLI. Teams then asked for editor integrations, so we added ACP and a JSON protocol for external clients. The next request was more direct: teams wanted the agent loop inside product surfaces, internal tools, terminals, dashboards, and deployment flows.
The Code Agent SDK is that embedding layer. Start an agent, stream every event, handle permission requests, and keep session state close to the app that owns the workflow.
main.ts
import { AutohandSDK } from '@autohandai/agent-sdk';
async function main() {
const sdk = new AutohandSDK({ cwd: '.', debug: true });
await sdk.start();
for await (const event of sdk.streamPrompt({
message: 'List the main source files and tell me what looks risky.'
})) {
if (event.type === 'message_update') {
process.stdout.write(event.delta);
}
}
await sdk.stop();
}
main();
main.py
import asyncio
from autohand_sdk import AutohandSDK
async def main():
async with AutohandSDK(cwd='.') as sdk:
async for event in sdk.stream_prompt('List the main source files and tell me what looks risky.'):
if event['type'] == 'message_update':
print(event.get('delta', ''), end='')
asyncio.run(main())
main.go
package main
import (
"context"
"fmt"
"log"
autohand "github.com/autohandai/agent-sdk-go"
)
func main() {
ctx := context.Background()
sdk := autohand.NewSDK(&autohand.Config{CWD: "."})
if err := sdk.Start(ctx); err != nil {
log.Fatal(err)
}
defer sdk.Close()
events, err := sdk.StreamPrompt(ctx, &autohand.PromptParams{
Message: "List the main source files and tell me what looks risky.",
})
if err != nil {
log.Fatal(err)
}
for event := range events {
if e, ok := event.(autohand.MessageUpdateEvent); ok {
fmt.Print(e.Delta)
}
}
}
Main.java
import ai.autohand.sdk.sdk.Agent;
import ai.autohand.sdk.sdk.AgentOptions;
import ai.autohand.sdk.types.Events;
public final class Main {
public static void main(String[] args) throws Exception {
Agent agent = Agent.create(AgentOptions.builder()
.cwd(".")
.instructions("Be concise and specific.")
.build());
var run = agent.send("List the main source files and tell me what looks risky.");
run.stream(event -> {
if (event instanceof Events.MessageUpdateEvent mue) {
System.out.print(mue.delta());
}
});
agent.close();
}
}
main.swift
import AgentSDK
import Foundation
let provider = OpenAIProvider(apiKey: "sk-...")
let agent = Agent(
name: "Reviewer",
instructions: "Be concise and specific.",
tools: [.readFile, .bash],
model: ModelID("gpt-4o"),
provider: provider
)
let stream = Runner.runStream(
agent: agent,
prompt: "List the main source files and tell me what looks risky."
)
for try await event in stream {
if event.type == .content, let data = event.data {
print(data, terminator: "")
}
}
main.rs
use autohand_sdk::{Agent, Config, Result};
#[tokio::main]
async fn main() -> Result<()> {
let mut agent = Agent::create(
Config::from_env()
.with_cwd(".")
.with_instructions("Review code with senior Rust judgement."),
)
.await?;
let result = agent
.run("List the main source files and tell me what looks risky.")
.await?;
println!("{}", result.text);
agent.close().await?;
Ok(())
}
main.rb
require "autohand_sdk"
AutohandSDK::Agent.open(
cwd: ".",
instructions: "Review code with staff-level Ruby judgement.",
permission_mode: "interactive"
) do |agent|
run = agent.send("List the main source files and tell me what looks risky.")
run.stream.each do |event|
print event["delta"] if event["type"] == "message_update"
end
result = run.wait
puts result.fetch(:text)
end
Program.cs
using Autohand.CodeAgentSdk;
await using var agent = await Agent.CreateAsync(new AgentOptions
{
WorkingDirectory = ".",
Instructions = "Review code with staff-level C# judgement.",
});
var run = agent.Send("List the main source files and tell me what looks risky.");
await foreach (var item in run.StreamAsync())
{
if (item is MessageUpdateEvent message)
{
Console.Write(message.Delta);
}
}
var result = await run.WaitAsync();
Console.WriteLine(result.Text);
main.cpp
#include <autohand/sdk.hpp>
#include <iostream>
int main() {
autohand::Agent agent(
autohand::Config::from_environment()
.with_cwd(".")
.with_instructions("Review code with senior C++ judgement."));
auto run = agent.send("List the main source files and tell me what looks risky.");
run.stream([](const autohand::SdkEvent& event) {
if (event.type == "message_update") {
std::cout << event.text_delta();
}
});
auto result = run.wait();
std::cout << result.text << "\n";
agent.close();
}Language status
The SDK family now includes the CLI-backed wrappers for TypeScript, Python, Go, Java, Rust, Ruby, C#/.NET, and C++, plus the native Swift SDK.
Ruby
Ruby gem with enumerator streams, Rails-friendly configuration, and JSON helpers.
Read the guideCore workflow
Every CLI-backed SDK page in this section follows the same runtime path.
- Start or create an agent session.
- Send a prompt or prompt params object.
- Stream
message_update,tool_*, andpermission_requestevents. - Reply to approvals when the runtime pauses.
- Wait for the final result or keep the session alive for the next run.
What you get
Stream the runtime
Build terminal UIs, approval flows, logs, and structured automations from typed events instead of scraping plain text output.
Control autonomy
Choose interactive review, restricted execution, or unattended runs, then answer approval requests from your own interface.
Keep context alive
Reuse an agent across prompts, preserve history, and separate planning steps from execution inside the same application flow.
Operate the CLI through typed APIs
Reset conversations, hand off browser sessions, run auto-mode, answer approval protocols, attach history, manage MCP and learning, and inspect the live tool registry.
Open runtime controlsExtend the agent
Use built-in file, shell, git, and search tools, then add MCP or custom tools when your product needs domain-specific actions.
Next steps
Quickstart
Pick a language, install the SDK, and run a first prompt with current package names.
Open quickstartApprovals
Wire the permission flow so your app can pause, ask, allow, or deny cleanly.
Read approvalsCLI runtime control
Use the full cross-language control surface for sessions, auto-mode, MCP, learning, tools, and context.
Read runtime controlsLanguage guides
Jump into the language-specific setup and event examples for your runtime.
Start with TypeScript