Skip to content

Conversation

@xingyaoww
Copy link
Collaborator

@xingyaoww xingyaoww commented Dec 29, 2025

Summary

This PR adds source variant builds alongside the existing binary builds for all server images (python, java, golang). This addresses issue #1531 where custom tools do not work with binary agent server builds.

Problem

When the agent server is bundled into a binary executable using PyInstaller (the binary target in the Dockerfile), custom tools cannot be dynamically imported at runtime because:

  1. PyInstaller creates a frozen executable with all Python modules bundled inside
  2. The frozen Python interpreter can only import modules that were bundled at build time
  3. External Python files copied into the Docker image are not accessible to the binary's internal importer

Solution

Add source variant builds that use the Python source with a full interpreter, which supports custom tools via dynamic module loading (importlib.import_module()).

Changes

  • Build matrix expanded: 12 jobs total (3 variants × 2 targets × 2 architectures)
    • Binary target: Production mode with PyInstaller binary (smaller, faster startup)
    • Source target: Development mode with Python source (supports custom tools)
  • Updated merge-manifests job: Now handles both binary and source variants
  • Updated consolidate-build-info: Tracks target information for PR descriptions
  • Updated PR description template: Documents binary vs source targets

Image Tags

After this change, users can choose between:

  • ghcr.io/openhands/agent-server:<sha>-python - Binary build (production)
  • ghcr.io/openhands/agent-server:<sha>-python-source - Source build (supports custom tools)

Closes #1531

Checklist

  • If the PR is changing/adding functionality, are there tests to reflect this?
    • This is a CI workflow change, not application code. The workflow itself will be tested when it runs.
  • If there is an example, have you run the example to make sure that it works?
    • N/A - This is a CI workflow change
  • If there are instructions on how to run the code, have you followed the instructions and made sure that it works?
    • N/A - This is a CI workflow change
  • If the feature is significant enough to require documentation, is there a PR open on the OpenHands/docs repository with the same branch name?
    • Documentation may be needed to explain when to use binary vs source images
  • Is the github CI passing?
    • Will be verified after PR is created

@xingyaoww can click here to continue refining the PR


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Target Architectures Base Image
golang-source source amd64, arm64 golang:1.21-bookworm
java binary amd64, arm64 eclipse-temurin:17-jdk
python-source source amd64, arm64 nikolaik/python-nodejs:python3.12-nodejs22
python binary amd64, arm64 nikolaik/python-nodejs:python3.12-nodejs22
java-source source amd64, arm64 eclipse-temurin:17-jdk
golang binary amd64, arm64 golang:1.21-bookworm

Note: binary targets are production-optimized PyInstaller builds. source targets support custom tools via dynamic module loading.

Pull (multi-arch manifest)

# Binary variant (production, smaller image)
docker pull ghcr.io/openhands/agent-server:2280f38-python

# Source variant (supports custom tools)
docker pull ghcr.io/openhands/agent-server:2280f38-python-source

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-2280f38-python \
  ghcr.io/openhands/agent-server:2280f38-python

All tags pushed for this build

ghcr.io/openhands/agent-server:2280f38-golang-amd64
ghcr.io/openhands/agent-server:2280f38-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:2280f38-golang-arm64
ghcr.io/openhands/agent-server:2280f38-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:2280f38-golang-source-amd64
ghcr.io/openhands/agent-server:2280f38-golang_tag_1.21-bookworm-source-amd64
ghcr.io/openhands/agent-server:2280f38-golang-source-arm64
ghcr.io/openhands/agent-server:2280f38-golang_tag_1.21-bookworm-source-arm64
ghcr.io/openhands/agent-server:2280f38-java-amd64
ghcr.io/openhands/agent-server:2280f38-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:2280f38-java-arm64
ghcr.io/openhands/agent-server:2280f38-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:2280f38-java-source-amd64
ghcr.io/openhands/agent-server:2280f38-eclipse-temurin_tag_17-jdk-source-amd64
ghcr.io/openhands/agent-server:2280f38-java-source-arm64
ghcr.io/openhands/agent-server:2280f38-eclipse-temurin_tag_17-jdk-source-arm64
ghcr.io/openhands/agent-server:2280f38-python-amd64
ghcr.io/openhands/agent-server:2280f38-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-amd64
ghcr.io/openhands/agent-server:2280f38-python-arm64
ghcr.io/openhands/agent-server:2280f38-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-arm64
ghcr.io/openhands/agent-server:2280f38-python-source-amd64
ghcr.io/openhands/agent-server:2280f38-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-source-amd64
ghcr.io/openhands/agent-server:2280f38-python-source-arm64
ghcr.io/openhands/agent-server:2280f38-nikolaik_s_python-nodejs_tag_python3.12-nodejs22-source-arm64
ghcr.io/openhands/agent-server:2280f38-golang
ghcr.io/openhands/agent-server:2280f38-golang-source
ghcr.io/openhands/agent-server:2280f38-java
ghcr.io/openhands/agent-server:2280f38-java-source
ghcr.io/openhands/agent-server:2280f38-python
ghcr.io/openhands/agent-server:2280f38-python-source

About Multi-Architecture Support

  • Each variant tag (e.g., 2280f38-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 2280f38-python-amd64) are also available if needed

Binary vs Source Targets

  • Binary: Production-optimized PyInstaller builds. Smaller image size, faster startup. Does not support custom tools.
  • Source: Python source with full interpreter. Larger image size, but supports custom tools via dynamic module loading.

This change adds source variant builds alongside the existing binary builds
for all server images (python, java, golang). Source builds support custom
tools via dynamic module loading, while binary builds remain optimized for
production use.

Changes:
- Add source target to build matrix (12 jobs total: 3 variants × 2 targets × 2 architectures)
- Update merge-manifests job to handle source variants
- Update consolidate-build-info to track target information
- Update PR description to document binary vs source targets

This addresses issue #1531 by providing source mode images that support
custom tools, while maintaining binary mode images for production deployments.

Closes #1531

Co-authored-by: openhands <openhands@all-hands.dev>
@openhands-ai
Copy link

openhands-ai bot commented Dec 29, 2025

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • Agent Server

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #1536 at branch `openhands/add-source-variant-builds`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

@xingyaoww
Copy link
Collaborator Author

@OpenHands please fix the failing actions on PR #1536 at branch openhands/add-source-variant-builds

@openhands-ai
Copy link

openhands-ai bot commented Dec 29, 2025

I'm on it! xingyaoww can track my progress at all-hands.dev

The merge-manifests job was failing because it expected tags in the format
`{sha}-{variant}-source-{arch}` (e.g., 050f42f-golang-source-amd64), but
build.py was generating tags with the target suffix after the arch suffix
(e.g., 050f42f-golang-amd64-source).

Changes:
- Remove -source suffix from CUSTOM_TAGS in workflow since build.py handles it
- Update build.py to place target suffix before arch suffix in all_tags
- Update consolidate-build-info to construct KEY with target suffix

Co-authored-by: openhands <openhands@all-hands.dev>
@openhands-ai
Copy link

openhands-ai bot commented Dec 29, 2025

Summary

I fixed the failing "Agent Server" GitHub Actions workflow on PR #1536. The issue was in the "Merge Multi-Arch Manifests" jobs for golang-source and java-source variants.

Root Cause

The merge-manifests job expected image tags in the format {sha}-{variant}-source-{arch} (e.g., 050f42f-golang-source-amd64), but the build process was generating tags with the target suffix after the arch suffix (e.g., 050f42f-golang-amd64-source).

This happened because:

  1. The workflow set CUSTOM_TAGS to include -source for source builds: golang-source
  2. build.py also appended -{target} suffix when target != "binary"
  3. This resulted in double -source suffix with wrong ordering

Changes Made

  1. .github/workflows/server.yml:

    • Changed CUSTOM_TAGS to just use the variant without -source suffix (since build.py handles it)
    • Updated consolidate-build-info job to construct the KEY with target suffix for proper grouping
  2. openhands-agent-server/openhands/agent_server/docker/build.py:

    • Modified all_tags property to place target suffix before arch suffix
    • Tags now correctly generate as {sha}-{variant}-{target}-{arch} (e.g., 050f42f-golang-source-amd64)

Verification

Tested the fix locally:

  • Source build: ghcr.io/openhands/agent-server:050f42f-golang-source-amd64
  • Binary build: ghcr.io/openhands/agent-server:050f42f-golang-amd64

The changes have been pushed to the openhands/add-source-variant-builds branch and the CI workflow should now pass.

View full conversation

@all-hands-bot all-hands-bot requested a review from rbren January 1, 2026 12:18
@all-hands-bot
Copy link
Collaborator

[Automatic Post]: I have assigned @rbren as a reviewer based on git blame information. Thanks in advance for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom tools do not work with binary agent server builds

4 participants