Open source · embeddable agent runtime

Add A3S Codeto an existing product

A coding-agent runtime that checks tools before they run, records each run step in a fact log, and completes a turn that changed files only with verification bound to that change. Embed the Rust, Node.js, Python, or Go SDK, or run a3s code in a repo.

a3s codeCLI
curl --proto '=https' --tlsv1.2 -LsSf https://raw.githubusercontent.com/A3S-Lab/a3s/main/install.sh | sh
a3s code
a3s code~/workspace/a3s

a3s-code v9.1.0·openai/gpt-5·12 skills·~/workspace/a3s

Type a message · / for commands · Shift+Tab cycles agent/plan/reviewer/auto/yolo · /ask = plan (read-only) · Ctrl+G reviews diffs · Ctrl+C twice to exit

You

Audit this repo for release risks offline; generate a report

ArtifactHTML · 18.4 KB
release-risk-report/index.htmlOpen viewRemoteUI
RemoteUIready
Release risk report2 risks · 12 checks
A3S Code

Review complete. Three subagents finished in parallel; the report artifact is ready to open in RemoteUI.

  1. Read repo constraints and release config

  2. Check code, tests, and docs in parallel

  3. Publish report artifact and open RemoteUI

◇ high

agentctx:12%a3sgit:(main)gpt-5 (128k context)
WHY A3S CODE

Tool calls hit your rules before the filesystem or shell

The model cannot touch files or run commands until the runtime checks arguments, permissions, and approvals. A call that needs approval parks in the fact log until your app answers. Execution streams back to your app as events.

01

Check files, shell, Git, and external requests

After the model or a pre-hook supplies tool arguments, the runtime validates the schema again, then checks workspace capability and permission policy. Calls that need approval park in the fact log until the host answers.

hookspolicyHITLsandbox
02

Project large output with verifiable evidence

A pinned policy can retain head and tail, fold repeated lines, and sample JSON. The model receives projected content; the app gets byte, hash, and loss evidence while artifacts keep the original.

transformevidenceartifact
03

Render the AgentEvent stream

Text, tool calls, plans, approvals, and lifecycle changes have explicit event types. A terminal, IDE, or web app can consume the same stream.

AgentEventEventEnvelopeV1
04

Changed files need verification to complete

A turn that mutated the workspace completes only when a Passed verification report is bound to that mutation’s effect digest, or a host waiver covers it. Assistant text never counts as evidence.

completion gateverificationdigest
A3S CODE / DISTINCTIVE CAPABILITIES

Five decisive moments that make a coding run safer and smarter

From approval before execution to code semantics, on-demand platform discovery, and past-session recall: select a scenario to see the real interaction order and boundaries in the A3S Code TUI.

Read the complete TUI guide
a3s code~/workspace/a3s

Push main to origin after the tests pass

Preparinggit push origin main
◇ high

agentctx:12%a3sgit:(main)gpt-5 (128k context)
HOW IT RUNS

Walk through one Python run

This uses the real a3s_code API from the repo. Click the steps to see Session, policy, events, and persistence get added. Each session runs one actor that folds the fact log; it is the default coding_actor unless Meta Harness recomposes it.

Read the Meta Harness guide
ACTIVE LAYERWays to use it
runtime.pyPYTHON
from contextlib import closing
from pathlib import Path
from a3s_code import Agent
workspace = str(Path.cwd())
with closing(Agent.create("agent.acl")) as agent:
pass
ACTIVE LAYERAgent and session
runtime.pyPYTHON
from contextlib import closing
from pathlib import Path
from a3s_code import Agent, LocalWorkspaceBackend, SessionOptions
workspace = str(Path.cwd())
options = SessionOptions()
options.planning_mode = "disabled"
options.workspace_backend = LocalWorkspaceBackend(workspace)
with closing(Agent.create("agent.acl")) as agent:
with closing(agent.session(workspace, options)) as session:
pass
ACTIVE LAYERContext, memory, and models
runtime.pyPYTHON
from contextlib import closing
from pathlib import Path
from a3s_code import Agent, LocalWorkspaceBackend, SessionOptions
workspace = str(Path.cwd())
options = SessionOptions()
options.planning_mode = "disabled"
options.auto_compact = True
options.auto_compact_threshold = 0.8
options.max_context_tokens = 128_000
options.workspace_backend = LocalWorkspaceBackend(workspace)
with closing(Agent.create("agent.acl")) as agent:
with closing(agent.session(workspace, options)) as session:
pass
ACTIVE LAYERPermission and execution checks
runtime.pyPYTHON
from contextlib import closing
from pathlib import Path
from a3s_code import (
Agent,
LocalWorkspaceBackend,
PermissionPolicy,
SessionOptions,
)
workspace = str(Path.cwd())
options = SessionOptions()
options.planning_mode = "disabled"
options.auto_compact = True
options.auto_compact_threshold = 0.8
options.max_context_tokens = 128_000
options.permission_policy = PermissionPolicy(
allow=["read*", "ls*", "glob*", "grep*", "code_*"],
deny=["write*", "edit*", "patch*", "bash*", "git*"],
default_decision="deny",
)
options.workspace_backend = LocalWorkspaceBackend(workspace)
with closing(Agent.create("agent.acl")) as agent:
with closing(agent.session(workspace, options)) as session:
pass
ACTIVE LAYERProject files and tools
runtime.pyPYTHON
from contextlib import closing
from pathlib import Path
from a3s_code import (
Agent,
EventType,
LocalWorkspaceBackend,
PermissionPolicy,
SessionOptions,
)
workspace = str(Path.cwd())
options = SessionOptions()
options.planning_mode = "disabled"
options.auto_compact = True
options.auto_compact_threshold = 0.8
options.max_context_tokens = 128_000
options.permission_policy = PermissionPolicy(
allow=["read*", "ls*", "glob*", "grep*", "code_*"],
deny=["write*", "edit*", "patch*", "bash*", "git*"],
default_decision="deny",
)
options.workspace_backend = LocalWorkspaceBackend(workspace)
with closing(Agent.create("agent.acl")) as agent:
with closing(agent.session(workspace, options)) as session:
for event in session.stream(
"Find the authentication entry points. Do not change files."
):
if event.type == EventType.TEXT_DELTA and event.text:
print(event.text, end="", flush=True)
elif event.type == EventType.TOOL_START:
print(f"\n→ {event.tool_name or 'tool'}")
elif event.type == EventType.ERROR:
raise RuntimeError(event.error or "A3S Code run failed")
ACTIVE LAYEREvents, records, and recovery
runtime.pyPYTHON
from contextlib import closing
from pathlib import Path
from a3s_code import (
Agent,
EventType,
FileSessionStore,
LocalWorkspaceBackend,
PermissionPolicy,
SessionOptions,
)
workspace = str(Path.cwd())
options = SessionOptions()
options.planning_mode = "disabled"
options.auto_compact = True
options.auto_compact_threshold = 0.8
options.max_context_tokens = 128_000
options.permission_policy = PermissionPolicy(
allow=["read*", "ls*", "glob*", "grep*", "code_*"],
deny=["write*", "edit*", "patch*", "bash*", "git*"],
default_decision="deny",
)
options.workspace_backend = LocalWorkspaceBackend(workspace)
options.session_store = FileSessionStore(".a3s/sessions")
with closing(Agent.create("agent.acl")) as agent:
with closing(agent.session(workspace, options)) as session:
for event in session.stream(
"Find the authentication entry points. Do not change files."
):
if event.type == EventType.TEXT_DELTA and event.text:
print(event.text, end="", flush=True)
elif event.type == EventType.TOOL_START:
print(f"\n→ {event.tool_name or 'tool'}")
elif event.type == EventType.ERROR:
raise RuntimeError(event.error or "A3S Code run failed")
runs = session.runs()
if runs:
current = runs[-1]
print(f"\nrun={current['id']} status={current['status']}")
session.save()
WHAT YOU GET

What the runtime ships with

The Rust crate defaults to the coding harness. Advanced evaluation, server, and headless search are Cargo features; the published Node.js and Python packages include advanced-harness and server. Basic search does not need embeddings or a vector DB.

TOOL CALLS

Workspace and policy determine the tool list

Files, search, shell, Git, web, batch, QuickJS, structured output, and child tasks are exposed only when the current workspace supports them and policy allows them.

filesshellgitwebprogramtask
MODELS

Change the model adapter, not the Session API

Use Anthropic, Zhipu, OpenAI-compatible APIs, or inject your own LlmClient.

streamingtoolsstructured output
RUN DATA

Runs, events, and snapshots use stable formats

Each run appends to a fact log under .a3s/effect-log; resume folds that log to pick the next step and never re-sends stored model turns. SessionSnapshotV1 commits sessions, runs, traces, artifacts, and verification results as one generation.

fact logSessionSnapshotV1auditable
EXTENSIONS

Extend tools, context, and storage

Replace or extend MCP, Skills, ContextProvider, MemoryStore, SessionStore, workspace services, and custom tools.

MCPSkillstraits
WORKSPACE RETRIEVAL

Build asynchronously; release with the session

Incremental BM25, optional host embeddings, in-memory vector partitions, and hybrid RRF share one bounded text catalog. No vector database is required, and non-text files never enter chunking or embeddings.

BM25semanticRRFCPU rerank
USE IT YOUR WAY

CLI in a repo, or four SDKs in your product

Run a3s code locally. For an IDE, runner, or your own UI, pick Rust, Node.js, Python, or Go.

Terminal

a3s code

A ready-to-run terminal UI for reasoning, tool calls, approval prompts, task progress, and diffs.

a3s code
Rust

a3s-code-core

The complete async runtime API, plus public traits for custom integrations.

cargo add a3s-code-core
Node.js

@a3s-lab/code

Native N-API bindings for sessions, event streams, tools, storage, orchestration, and MCP.

npm install @a3s-lab/code
Python

a3s-code

A native PyO3 package with both synchronous and asynchronous APIs.

python -m pip install a3s-code
Go

sdk/go/v9

A pure-Go API for sessions, event streams, tools, verification, and MCP through a long-lived bridge, without CGO.

go get github.com/A3S-Lab/Code/sdk/go/v9
WHAT STAYS YOURS

We run the agent; you own accounts and UI

  • Core is an agent runtime, not a hosted service, and it does not dictate your UI.
  • The terminal UI comes from the separate A3S CLI.
  • Accounts, credentials, deployment, and which app tools are callable stay yours.
Read the architecture guide
TRY IT

Try it in a repo you already have

Install a3s code and run it once. Embed later with Rust, Node.js, Python, or Go if you need to.