Commit Graph
35 Commits
Author SHA1 Message Date
JBD dc4f36cdba Restructure AX into a general-purpose orchestration layer for agentic tasks
AX is undergoing a significant redesign, moving away from a single CLI with
an embedded Python harness toward a general-purpose orchestration layer for
agentic tasks. The repository is reorganized around three binaries: ax-server
exposes a gRPC API for submitting Task manifests, ax-controller runs as a
horizontally scaled reconciler that consumes work from Redis Streams, and
ax-task-runner executes tasks inside sandboxed workers. Task state now lives
in Redis rather than Kubernetes CRDs so the system can handle millions of
short-lived tasks without straining etcd. The legacy Python harness, ATE
client, SQL event log, and skill examples are removed, and new design,
concepts, manifest, networking, runner, and sandbox docs plus Kubernetes
deploy manifests describe the new architecture.
2026-09-19 20:14:43 -07:00
Jaana Dogan 2282424ebc Make the public facing ExecutionService more InteractionsService-like (#339)
We want AX to be compatible with the Interactions API protocol as much as possible. This PR aligns the proto with Steps and with the Interactions semantics. We will follow up with more changes to make it more compatible with Interactions while preserving a `conversation_id` based history model.

`ConversationService` is removed for now until we know what kind of data operations we want to provide for event log management.
2026-08-11 22:52:05 -07:00
Joyce Liu a34bbebf2d antigravity: remove _resolve_localhost /etc/hosts hack (#328)
google-antigravity 0.1.7's _connect_websocket retries both "localhost"
and "127.0.0.1" when dialing localharness (local_connection.py:993), so
the sidecar no longer needs to patch /etc/hosts for substrate/gVisor
environments where localhost may not resolve.

Ref #325

antigravity: guard conversation_id for safe save_dir use (#312)

harness_server uses the caller-supplied conversation_id directly as a
per-conversation storage directory name (save_dir = state_dir /
conversation_id) before the Antigravity harness ever sees it, so a value
like "../escape" could traverse outside state_dir. Reject an empty id or
one containing a path separator or a "." / ".." component at the boundary
in _run_turn, returning an INVALID_ARGUMENT end frame.

This is intentionally only a path-safety guard, not the id-format
contract. The Antigravity harness owns that: it validates the forwarded
cascade_id (length and character set) per cl/948016352. Keeping the
format rule in one place avoids the two layers drifting.

chore: remove stale docs, gitignore, and Makefile entries (#329)

- CONTRIBUTING.md: drop 'make run-remote' (no such Makefile target)
- .gitignore: remove orphaned entries (local/remote_agent, sandbox-router,
  tasklog, axepp, google-cloud-sdk, test-sandbox-config.yaml)
- Makefile: add missing deps, clean-logs to .PHONY

antigravity: remove vertex env-var override (superseded by AGY 0.1.7) (#331)

* antigravity: remove vertex env-var override (superseded by AGY 0.1.7)

google-antigravity 0.1.7 reads GOOGLE_GENAI_USE_VERTEXAI /
GOOGLE_GENAI_USE_ENTERPRISE + GOOGLE_CLOUD_{PROJECT,LOCATION} natively,
so the sidecar no longer needs _vertex_kwargs_from_env to thread them
into LocalAgentConfig.

- Delete _vertex_kwargs_from_env + VertexKwargs.
- _build_default_config: bare LocalAgentConfig(system_instructions=...).
- _has_credentials: read project/location from env (SDK hydrates them
  onto VertexEndpoint, not LocalAgentConfig).
- Update tests accordingly.

Requires the 0.1.7 bump. Credential resolution is startup-only and
does not touch the save_dir/state_dir resume path.

Ref #325

* antigravity: drop stale _has_credentials docstring note about vertex env override

Interactions: persist interactions harness with durable dir and resume from it (#327)

interactions: make WorkDir authoritative for run_command (#335)

The interactions harness executed run_command relative to the process's
ambient working directory, which is not reliably the agent's workspace: with
no Cwd argument the command ran wherever the process cwd happened to be, and a
model-supplied Cwd (including "/") was honored blindly. As a result tool calls
often ran from "/" instead of the configured workspace (#332).

Make the workspace directory authoritative in the executor rather than relying
on ambient process state:

- Add AntigravityInteractionsConfig.WorkDir (defaults from AX_HARNESS_WORKDIR).
- run_command now resolves its directory via resolveRunDir: no Cwd -> WorkDir;
  relative Cwd -> joined under WorkDir; absolute Cwd -> honored as-is. Empty
  WorkDir preserves the previous process-cwd behavior.
- Add WorkspaceSystemInstruction to orient the agent about its working
  directory so it emits workspace-relative paths, and wire it in cmd/ax.

Fixes #332

Remove the binary (#334)

* Remove the binary

* chore: add e2e directory to .gitignore

* refactor: migrate binary file check to a dedicated workflow file

* fix: restrict binary file check to added, copied, or modified files
2026-07-20 18:22:45 -07:00
Joyce Liu 7437b2f633 ci: run Python tests for the antigravity harness sidecar (#296)
The 17 tests in python/antigravity/harness_server_test.py have never
run in CI. .github/workflows/go.yml only runs 'go test ./...' and the
Makefile 'test' target likewise only runs Go. That let PR #244 land
with 2 stale assertions unnoticed (fixed in #291).

Adds:
- .github/workflows/python.yml -- dedicated Python workflow (kept
  separate from the Go-only go.yml so each can evolve independently).
- Makefile 'test-python' target for local parity.

Test deps are inlined in the workflow rather than added as a separate
requirements-test.txt -- the diff is 2 packages ('pytest>=7.0',
'pytest-timeout>=2.0'), not worth its own file. Version floors match
the upstream google-antigravity SDK's dev extras so this doesn't
drift as pytest evolves.

--timeout=30 --timeout-method=thread guards against hung gRPC servers
so a stuck test can't eat the whole workflow budget.
2026-07-13 09:55:24 -07:00
Jaana Dogan 3f39ca3f91 Delete obsolete Makefile targets (#284) 2026-07-09 14:44:57 -07:00
Jaana Dogan 78f4a8f229 Add structured Error in HarnessEnd (#215)
- Added Error message to proto
- Removed error_message
- Updated the autogenerated artifacts
2026-06-29 00:03:41 -07:00
Jaana Dogan 6d3a5f1798 Remove AgentService (#186) 2026-06-26 08:42:18 -07:00
Jaana Dogan e7d5e2c8c6 Remove ununsed axepp (#182) 2026-06-26 08:41:45 -07:00
Jaana Dogan 9737fd7033 Migrate controller and registry to internal/controller2 (#176)
* Cleanup the repo and move to controller2

* Migrate controller and registry to internal/controller2

- Remove the legacy harness build tag

* refactor: move GeminiConfig definition from internal/config to internal/gemini package

* test: replace controller registry with dummy implementation and update dependency constraints in go.mod

* chore: remove harness build and test steps from GitHub Actions workflow
2026-06-25 15:21:28 -07:00
Jaana Dogan c281998ce7 refactor: remove ate build tag and consolidate server implementation (#119) 2026-06-16 07:37:57 -07:00
Junjie Wang 217d53fb2f Add the scaffolding for new configs in controller v2. (#48) 2026-06-05 11:04:19 -07:00
Jaana Dogan 3887ea5c69 Move axharness service to the ax binary (#42)
* Move axharness service to ax binary

This is for the simplicity of building everything into the same binary. In Substrate deployments, ax harness will be executed as an actor.

* feat: add harness implementation to support AGY and other service harnesses
2026-06-01 10:13:13 -07:00
Junjie Wang b8d190f32c Wire up controller2 and harness by a build tag. (#33) 2026-05-27 16:26:44 -07:00
Jaana Dogan 4d04e36470 Initial commit of the Substrate refactor (#17)
* Added internal/controller2/: as a copy of the existing controller.
* Added a new deployment manifest which will replace the previous one, internal/manifests/ax-deployment2.yaml.
* Added HarnessService to proto as a placeholder.
* Added internal/SUBSTRATE_REFACTOR_CLEANUPS.md for some cleanups after this refactor is done.
* Added SubstrateHarness that can create/resume axharness as an actor with conversation ID.
* Remove unnecessary ate build tags because Substrate is now public.

Updates #3.
2026-05-22 09:30:44 -07:00
Jaana Dogan 4f332b6387 Rename ATEAgent to SubstrateAgent (#362)
Naming cleanup for ax.yaml and the experimental example SubstrateAgent.
2026-05-16 19:12:44 -07:00
Jaana Dogan 9da8fad0ba Delete Kubernetes sandbox agents (#281)
So we don't accidentally promote this option. There are also rough edges
in this implementation that we don't have time to fix, e.g. the use of
kubectl.
2026-05-05 11:55:39 -07:00
Jaana Dogan 1cf68d66db Introduce a gRPC interceptor to suspend the server actor (#279)
We will revisit this. If in the 50 ms window, another request comes, the
client will disconnect when we suspend.
2026-05-04 21:01:06 -07:00
Jaana Dogan 55d5b1b1ea Deploy AX to Substrate (#228)
This change introduces an EPP to create/resume actor the incoming
conversation_id. We also introduce an ax-shell image and a demo pod for
testing purposes.

Follow up changes:
- Suspend the AX server automatically after the request is sent.
- Explore failure cases and how we can ensure suspension safely even if
AX server crashes.
- EventLogService.Fork shouldn't autogenerate a dest_conversation_id.
dest_conversation_id should always be supplied from the client for
routing.

This change also removes the RegisterAgent RPC. Actor
resumption/suspension requires a valid conversation_id for all RPCs and
RegisterAgent no longer fits into this new constraint.
2026-05-04 08:23:48 -07:00
Jaana Dogan d44fe1402f Move the Kubernetes sandbox router to experimental (#265) 2026-04-30 08:53:49 -07:00
Jaana Dogan 13a77b8946 Move experimental features to internal/experimental (#257)
Allows us to more easily track and update experimental features.
2026-04-27 10:02:42 -07:00
Jaana Dogan 3cce8cf42d Use the prebuilt k8s-sandbox-router image (#256) 2026-04-27 07:40:25 -07:00
Jaana Dogan 5dc999316a Use JSON encoding for agent configuration (#252)
We allow any encoding for sub agent configuration after
https://github.com/google-gemini/ax/pull/248. This change is removing
the proto encoding requirement for the Gemini and the test agents.
2026-04-26 20:16:39 -07:00
Jaana Dogan 88b82f35e5 Set KO_DOCKER_REPO environmental variable to a default (#227) 2026-04-18 18:06:28 -07:00
Jaana Dogan b02a2a0dce Use ko to build images (#223) 2026-04-17 13:59:54 -07:00
Jaana Dogan f32aebcdbf Add AX server ATE deployment manifest (#220) 2026-04-17 12:27:10 -07:00
Jaana Dogan 21f1141292 Fix the Dockerfile (#217) 2026-04-17 10:49:54 -07:00
Jaana Dogan 392a19e7e5 Introduce ATE agents (#213)
This pull request introduces initial support for integrating
experimental ATE (SubstrATE) agents. It also includes a complete example
with manifests and a sample agent implementation.

The changes are primarily focused on enabling optional ATE agent support
behind a build tag. CreateActor isn't always working but we will use
this experimental feature as a starting point.

ATE agents start and suspend actors for execution at every agent call.
In the future, we would like to make changes to the controller to make
native resumption of agents from the snapshots possible. For now, we are
creating and suspending at every agent call.

We will rename ATE once we have an external name for the project.
2026-04-17 10:04:09 -07:00
Jaana Dogan 83c8622d88 Split Content into its own protobuf file (#198)
We will soon replace this with the Interactions proto.
2026-04-14 09:23:52 -07:00
Jaana Dogan 863ae4abf2 Avoid duplicates of inputs in resumption (#108)
Inputs should only be appended to the history once the execution is
complete. Otherwise, they will cause duplicates in task event log.

Also remove Rehydrate option. There isn't a clear good use case for it
yet.
2026-03-18 15:54:42 -07:00
Jaana Dogan 3828779172 Rename the project name from GAR to AX (#95) 2026-03-16 14:06:13 -07:00
Jaana Dogan 7554465a1c Introduction of task executor (#91)
We are replacing the current loop executor with a new internal execution
framework. This update refactors the majority of the project's core
logic to improve stability and performance.

We introduce a new Task Executor, moving away from simple
request-response agent loops toward a more structured, stateful
execution model. The core of this update is the addition of a Task
struct and a TaskExecutor interface, which allow agents to trigger
sub-tasks and manage complex workflows. This change enables better
recursion and delegation between different agents, such as the testing
coding agent and specialized worker agents. The new executor framework
supports confirmation propagation and leaves the confirmation handling
to the agent implementation.

The update introduces a new persistent Event Log system to track every
step of a task's execution. By recording inputs, outputs, and state
changes to a newline-delimited JSON file, the system can now "rehydrate"
sessions at any point. This allows the executor to resume from a
consistent state after a crash or restart, and provides a durable
history of agent actions.

The change refactors the Controller and various agent implementations to
support these new interfaces. It includes updates to the CLI trigger
tool to handle interactive confirmation prompts more effectively and
manage conversation history across task boundaries. Comprehensive tests
for the new Task Manager, including fan-out execution and resume
capabilities, are also included to ensure reliability in concurrent
environments.

The change also introduces a "gemini" agent to make it easier to make
Gemini calls without having to write any new code. We default to the
Flash models but can follow up with some configuration options to
override the default settings.

Trigger now also allows starting execution from any available agent, `$
trigger --agent <agent_id>`.

The new capabilities can be explorable and testable with the
internal/testagent.

Follow up changes after this change is merged:
- Fixing Gemini planner and skills support
- gar trigger will be rename to gar exec
- We will remove the session IDs and replace them with IDs/task IDs
- Exec over the wire, changes to AgentService
- Task log in SQLite
- Trace view tool to be able to inspect the logs
2026-03-16 12:12:38 -07:00
JoyceLiu 786146bba9 Feature/gke sandbox agent (#81)
### Description
This PR introduces end-to-end support for dynamically provisioning,
managing, and routing to isolated K8s Sandbox environments on GKE for
secure agent execution as part of GAR

### Key Features & Components

#### 1. Kubernetes Resource Orchestration (`pkg/sandboxclient`)
Implemented a robust `dynamic` K8s client to programmatically interact
with the complete suite of Custom Resources required for GKE Agent
Sandbox:
* **`SandboxTemplate`**: Defined via manifest
(`examples/sandbox_agent/sandbox-template.yaml`) and injected via
`sandbox_template_ref` in `gar.yaml` to serve as the blueprint for the
container environment.
* **`SandboxWarmPool`**: Client APIs added
(`CreateWarmPool`/`DeleteWarmPool`) for pre-booting "warm" sandboxes to
eliminate cold-start latency.
* **`SandboxClaim`**: Client APIs added (`CreateClaim`/`DeleteClaim`) to
provision ephemeral execution environments and bind them exclusively to
a GAR `sessionID`.
* **`Sandbox`**: Polling APIs added (`WaitForSandbox`) to read the
resulting pod's `selector` and `status.service` IP once the Claim is
successfully fulfilled.

#### 2. Sandbox Agent Interface (`agent/sandbox.go`)
Added the `sandbox` agent type implementation.
* Deterministically maps a GAR `sessionID` to a K8s `SandboxClaim` name
for session reusability.
* Requests the lease, waits for the pod to become ready, establishes the
gRPC streaming connection via the Router, and handles automatic cleanup
of the K8s pod during `agent.Close()`.

#### 3. In-Cluster Sandbox Router (`cmd/sandbox-router`)
* Added a lightweight, high-performance gRPC proxy that runs natively
inside GKE.
* Securely bridges external `kubectl port-forward` traffic from the GAR
CLI directly to the isolated backend gVisor pods by parsing
`x-sandbox-id` headers.

#### 4. Enhancements & Fixes
* **Resiliency**: Enhanced `agent/remote.go` to support automatic
retries during internal network or port-forward disconnects.
* **Stability**: Fixed a panic in `internal/controller/health.go`
occurring during the health monitor shutdown sequence.
* **Example**: Provided a complete end-to-end sandbox example (Go
uppercase processor, Dockerfile, and K8s manifest) in
`examples/sandbox_agent/`.
* **Documentation**: Added comprehensive tutorials to `README.md` for
deploying the router, configuring warm pools, and testing the sandbox
examples. Includes a new `make build-router` target for easy proxy
cross-compilation.
* 

Tested manually with GKE agent sandbox 

**1. Compiled and Deployed the newly-coded K8s Router & Sandbox
Template**
```bash
$ make build-router
$ kubectl apply -f cmd/sandbox-router/sandbox-router.yaml
$ kubectl wait --for=condition=Ready pod -l app=sandbox-router --timeout=60s
$ kubectl apply -f examples/sandbox_agent/sandbox-template.yaml
```
``

**2. Built and Started the GAR Controller CLI**
```bash
$ make build
$ ./bin/gar serve --config gar.yaml > serve.log &
2026/03/07 02:28:18 Starting GAR server at :8494...
```

**3. Executed the Trigger**

```bash
$ ./bin/gar trigger --server localhost:8494 --input "test sandbox agent by converting 'hello from tty' to uppercase"
```

**4. The Result**
```
Session: 1338459a-40d2-45df-b0c5-a07512c3506a
⏺ test sandbox agent by converting 'hello from tty' to uppercase

hey im your sandbox agentHERE IS YOUR UPPERCASE TEXT: TEST SANDBOX AGENT BY CONVERTING 'HELLO FROM TTY' TO UPPERCASE
```

**5. Check the sandbox log 
```
$ kubectl logs gar-claim-uppercase-1338459a40d245dfb0c5 -n default


2026/03/07 10:33:11 🟢 upper_case_agent listening on :8494
2026/03/07 10:33:15 📥 Received request text: "test sandbox agent by converting 'hello from tty' to uppercase"
2026/03/07 10:33:15 📤 Sending response: "TEST SANDBOX AGENT BY CONVERTING 'HELLO FROM TTY' TO UPPERCASE"
```
2026-03-10 11:22:19 -07:00
JBD 63c815338c Fix run-local and run-remote 2026-01-21 16:09:29 -08:00
JBD 5c03f4ec1a Fix make build 2026-01-21 16:09:29 -08:00
JBD 4cd3212a1b Introduce GARService and controller 2026-01-21 16:09:22 -08:00