feat: add Northflank provider#3448
Conversation
NorthflankSandboxClient + NorthflankSandboxSession (BaseSandboxClient / BaseSandboxSession) run agent workspaces inside a Northflank service container. Two modes: * attach to an existing service (service_id) — client never deletes it. * ephemeral deployment (image_path) — client creates the deployment and deletes it on cleanup. owned_by_client is recorded in session state so resume() preserves the ownership decision. Exec goes through the V1 exec WebSocket; file IO uses the SDK's file-copy API; workspace persistence is tar through /tmp staging. Tar payloads are validated locally before extraction because tar -xf runs remotely and doesn't apply Python's filter='data' policy. NorthflankCtx + northflank_tools() expose curated @function_tool wrappers around the Northflank REST API (list/get projects + services, deploy + restart + pause + resume + scale + wait, exec in service/job/addon containers, fetch/tail logs, fetch metrics, plus gated delete/secret/volume/domain mutations). Mutating tools carry needs_approval=True. NorthflankShellExecutor wires the same exec channel into the ShellTool executor interface for agents that don't need a full sandbox. Adds the northflank optional extra (Python <3.14 since the Northflank Python SDK targets 3.9-3.13) and the mypy module override.
Three example runners: * examples/northflank/list_services.py — agent uses northflank_tools() to enumerate services in a project and summarise them. * examples/northflank/remote_shell.py — agent uses ShellTool wired to NorthflankShellExecutor so every shell command runs inside a target Northflank service. * examples/sandbox/extensions/northflank_runner.py — manual sandbox runner: small workspace, one shell tool, plus a stop/resume snapshot round-trip check against a real Northflank service.
c0da388 to
c0dab52
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c0dab526df
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| modal = ["modal==1.3.5"] | ||
| runloop = ["runloop_api_client>=1.16.0,<2.0.0"] | ||
| vercel = ["vercel>=0.5.6,<0.6"] | ||
| northflank = ["northflank>=1.0,<2; python_version < '3.14'"] |
There was a problem hiding this comment.
Update the lockfile for the new extra
This adds the northflank optional dependency, but the commit does not update uv.lock, while CI installs from the frozen lock (UV_FROZEN=1 + make sync/uv sync --all-extras). With the current lock the package is not installed, so the new Northflank tests that import northflank at collection time fail with ModuleNotFoundError; please regenerate and commit the lockfile entry for this extra.
Useful? React with 👍 / 👎.
| modal = ["modal==1.3.5"] | ||
| runloop = ["runloop_api_client>=1.16.0,<2.0.0"] | ||
| vercel = ["vercel>=0.5.6,<0.6"] | ||
| northflank = ["northflank>=1.0,<2; python_version < '3.14'"] |
There was a problem hiding this comment.
Do not exclude Northflank from the 3.14 test job
The dependency is guarded with python_version < '3.14', but the test workflow runs make sync/make tests on Python 3.14 (.github/workflows/tests.yml matrix includes 3.14). On that job --all-extras still omits northflank, while the new tests import northflank and agents.extensions.sandbox.northflank unconditionally during collection, so the 3.14 CI leg will fail unless the dependency is available there or those tests are skipped when it is not.
Useful? React with 👍 / 👎.
Summary
Adds a Northflank provider integration behind the optional
northflankextra.This includes:
agents.extensions.northflank.northflank_tools(): a curated tool namespace for operating Northflank resources from agents.agents.extensions.northflank.NorthflankShellExecutor: aShellToolexecutor that runs commands inside a Northflank service container.agents.extensions.sandbox.northflank.NorthflankSandboxClient: a hosted sandbox provider backed by Northflank services.Supported features
Northflank tools support:
Mutating, exec, and destructive tools are marked with
needs_approval=True. Delete, secret, volume, and domain tools are opt-in vianorthflank_tools(include_...).The sandbox provider supports:
workspace_persistence="volume") or a tar embedded in session state (workspace_persistence="tar").Usage
Install with the optional extra:
pip install "openai-agents[northflank]"Use Northflank tools with an authenticated SDK client:
Use the shell executor with
ShellTool:Use Northflank as a sandbox backend:
Workspace persistence
By default the sandbox workspace lives in the container filesystem and is dropped when the service is deleted. Two opt-in strategies let it survive stop/resume:
Volume mode — provisions a Northflank volume mounted at
manifest.root, attached to the service. The volume survives stop/resume and is deleted byclient.delete()if the client created it. Only valid withimage_path(client-owned services).volume_specdefaults to a 5120 MiBnf-multi-rwvolume inReadWriteManymode (5120 MiB is the smallest size Northflank accepts on that storage class). Override it to use a different size, storage class, or access mode:Tar mode — at
stop()the workspace is tarred via exec and embedded (base64) into the session state. Onresume()the tar is uploaded and extracted back into the workspace.Examples
northflank_tools().ShellToolagainst a Northflank service.Tests
Unit coverage for the Northflank tools, shell executor, and sandbox client/session behavior.