Skip to content

About

Embeddable agent runtime (agent harness) for Android and the JVM: agent loop, sandboxed workspace, MCP, skills, subagents, hooks. Bring your own model.

Topics

Resources

Contributing

Security policy

Stars

13 stars

Watchers

1 watching

Forks

Latest commit

 

History

61 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Android Agent Runtime

CI Maven Central License: MIT Kotlin Android API

English | 中文

An embeddable agent runtime (an agent harness) for Android and the JVM. It runs a full agent loop inside your app's process: a sandboxed workspace the agent reads and writes, tools from your code and from MCP servers, skills and subagents, hooks and policy around every tool call, and durable sessions. Bring any OpenAI- or Anthropic-compatible model.

0.5.0 is not published yet. This branch uses the new Thread / Turn / Item API. Build from source or run ./gradlew publishToMavenLocal and add mavenLocal() to your repositories. Maven Central still has 0.4.0; its API differs from these examples. See the migration guide.

What you get

  • The agent loop, on the device. Native tool calling with streaming, thinking, prompt caching and server-side web search where the provider has them; retries, budgets and conversation compaction that summarizes old turns.
  • A sandboxed workspace. A virtual file system the agent works in; mount app directories, assets, in-memory sources or a folder the user picks (SAF). Nothing outside what you mount is reachable.
  • Tools. Plain Kotlin functions (functionTools), any ToolProvider, and remote MCP servers over Streamable HTTP (McpHttpClient, built in). With many tools the agent searches for the right ones instead of seeing them all.
  • Skills, AGENTS.md and subagents. Skills load on demand; the agent can delegate to child agents and wait for them.
  • Control. Hooks before and after tool calls, a policy engine, confirmation for network and side-effecting actions, and a per-provider concurrency limit.
  • Durable sessions. An append-only event log per session, resumable runs, SQLite session storage on Android.
  • Optional modules. Operate other apps' screens through accessibility (Android Use), sandboxed JavaScript that calls tools, calendar, notification and media tools, and A2A client and server.

Install

dependencies {
    implementation(platform("cc.noharry:agent-bom:0.5.0-SNAPSHOT"))
    implementation("cc.noharry:agent-runtime-android") // an Android app
    // implementation("cc.noharry:agent-runtime")      // the JVM: a server, a desktop tool, tests
}

Kotlin 2.0 or later (the artifacts are built at language level 2.1), JDK 17, Android minSdk 23. The workspace and the event log use java.nio.file, which Android has from API 26: below that, enable core library desugaring with com.android.tools:desugar_jdk_libs_nio 2.1.5 or later (as samples/quickstart-android does).

Quickstart (Android)

val tools = functionTools("device") {
    tool("device_info", "The phone or tablet this app runs on.", readOnly = true) {
        "${Build.MANUFACTURER} ${Build.MODEL}, Android ${Build.VERSION.RELEASE}"
    }
}

val runtime = AndroidAgentRuntime.builder(context) // workspace, SQLite sessions, event log, history
    .model(OpenAiModelClient({ apiKey }, model = "gpt-4o-mini", stream = true))
    .tools(tools)
    .build()

scope.launch {
    runtime.startThread().runStreamed("What device am I on?")
        .collect { event -> if (event is ThreadEvent.ItemDelta) answer.append(event.text) }
}

Use thread.run(text) for a complete TurnResult, or runStreamed for eight event types. Each item has a stable id, and ItemCompleted includes its full content. An Approval item waits in the same stream until approve() or deny(); ask finishes with WAITING_FOR_ANSWER, and the next turn supplies the answer. thread.steer(text) adds input while a turn runs; thread.interrupt() cancels it. Configure .storage(directory) on the JVM to restore model history and thread.items() after restarting; Android configures private storage automatically. Live tool payloads are original; stored item snapshots use the configured trace redactor.

Keep API keys off the device in a real app: point baseUrl at your own backend.

Quickstart (JVM, with an MCP server)

val deepWiki = McpToolProvider(
    McpHttpClient("https://mcp.deepwiki.com/mcp", headers = { emptyMap() }, http = OkHttpHttpTransport(),
        clientName = "my-app", clientVersion = "1.0"),
    serverId = "deepwiki",
)

val runtime = AgentRuntime.builder()
    // Any OpenAI-compatible endpoint: pass its baseUrl. AnthropicModelClient speaks the Messages API.
    .model(OpenAiModelClient({ System.getenv("API_KEY") }, model = "gpt-4o-mini", stream = true))
    .tools(deepWiki)
    .workspaceRoot(File("agent-workspace"))
    .build()

The samples run as they are: AGENT_API_KEY=… ./gradlew :samples:quickstart-jvm:run --args="…", and samples/quickstart-android is a one-screen app. ./gradlew :samples:extensions:run needs no key or network: a model of your own (a scripted one standing in for an on-device model), tools from your code, and a hook that refuses a call.

Modules

Artifact What it is
agent-runtime The runtime and host facade (plain JVM): AgentRuntimeBuilder, OpenAI- and Anthropic-compatible model clients, MCP, functionTools, skills, subagents, sessions and memory, web search and fetch, hooks and policy, and the workspace's virtual file system
agent-runtime-android The Android layer: AndroidAgentRuntime.builder(context), SQLite sessions, the app-private event log, and mounting a folder the user picks through the Storage Access Framework
agent-api Android-neutral Thread / Turn / Item contracts and stable model, tool, hook and event-log extension interfaces
agent-exec-js Optional: exec_js, sandboxed JavaScript (QuickJS through Zipline) that can call tools
agent-device-capabilities Optional: calendar, notification and media tools
agent-android-use Optional: observe and operate the screen through an accessibility service
agent-a2a Optional (plain JVM): delegate tasks to remote A2A agents over a direct JSON-RPC/SSE transport, and expose the agent as a local A2A endpoint
agent-a2a-client-official Optional: the same client over the official A2A Java SDK
agent-bom One version for all of the above

An Android app depends on agent-runtime-android; a server, desktop tool or test uses agent-runtime. Optional modules depend at most on agent-api. The loop implementation is internal to agent-runtime; samples/minimal shows a host with only a model.

API stability

Starting with 0.5.0, the Thread / Turn / Item API and the main extension interfaces in cc.noharry.agent.spi are stable. Advanced diagnostic and tuning APIs remain experimental. The changelog records migrations.

  • Declarations marked @ExperimentalAgentRuntimeApi or @ExperimentalA2aClientApi are the likeliest to change, and ask for an opt-in (without one, the runtime's are a compile error and the A2A client's a warning).
  • Declarations marked @InternalAgentRuntimeApi are not API: they are there for the runtime's own modules and tests, and may change or go in any release.
  • The public API of every module is recorded in its api/*.api, which CI compares with the code, so no change to it goes unnoticed.

Security reports: see SECURITY.md.

Building from source

To try changes not yet released, clone this repository next to your project and let Gradle build it from source; the same coordinates resolve to it:

// settings.gradle.kts of your project
includeBuild("../android-agent-runtime")

Showcase

Bothy is a tablet-first demo built on this runtime: a floating voice assistant, public MCP servers, plans that watch a server's state, generative UI, and a simulated car head unit to drive.

Building

JDK 17 and the Android SDK. ./gradlew ciCheck runs what CI runs: the source rules, the API compatibility check, the Android API level checks and lint, every unit test and the sample builds. See CONTRIBUTING.md.

License

MIT. Third-party code and native libraries keep their own licenses; see THIRD_PARTY_NOTICES.md.

About

Embeddable agent runtime (agent harness) for Android and the JVM: agent loop, sandboxed workspace, MCP, skills, subagents, hooks. Bring your own model.

Topics

Resources

Contributing

Security policy

Stars

13 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages