From 648e659d7dc7485f9d517a7897fcf1f9f67c2326 Mon Sep 17 00:00:00 2001 From: Eric Curtin Date: Mon, 11 May 2026 22:28:48 +0100 Subject: [PATCH] feat(providers): add Docker Agent provider Add docker-agent as a built-in agent provider so Docker Agent (docker agent) can be sandboxed and policy-enforced within OpenShell. The profile covers the Docker Hub registry endpoints for pulling OCI agent images, the local Docker Model Runner endpoint for inference, and an optional Docker Hub access token for private agent repositories. Signed-off-by: Eric Curtin --- crates/openshell-providers/src/lib.rs | 2 + crates/openshell-providers/src/profiles.rs | 1 + .../src/providers/docker_agent.rs | 47 +++++++++++++++++++ .../openshell-providers/src/providers/mod.rs | 1 + providers/docker-agent.yaml | 32 +++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 crates/openshell-providers/src/providers/docker_agent.rs create mode 100644 providers/docker-agent.yaml diff --git a/crates/openshell-providers/src/lib.rs b/crates/openshell-providers/src/lib.rs index 3b28030ca..649bb0f84 100644 --- a/crates/openshell-providers/src/lib.rs +++ b/crates/openshell-providers/src/lib.rs @@ -84,6 +84,7 @@ impl ProviderRegistry { registry.register(providers::claude::ClaudeProvider); registry.register(providers::codex::CodexProvider); registry.register(providers::copilot::CopilotProvider); + registry.register(providers::docker_agent::DockerAgentProvider); registry.register(providers::opencode::OpencodeProvider); registry.register(providers::generic::GenericProvider); registry.register(providers::openai::OpenaiProvider); @@ -146,6 +147,7 @@ pub fn normalize_provider_type(input: &str) -> Option<&'static str> { "claude" => Some("claude"), "codex" => Some("codex"), "copilot" => Some("copilot"), + "docker-agent" | "docker_agent" => Some("docker-agent"), "opencode" => Some("opencode"), "generic" => Some("generic"), "openai" => Some("openai"), diff --git a/crates/openshell-providers/src/profiles.rs b/crates/openshell-providers/src/profiles.rs index 8c3f247cf..5321c56e7 100644 --- a/crates/openshell-providers/src/profiles.rs +++ b/crates/openshell-providers/src/profiles.rs @@ -19,6 +19,7 @@ const BUILT_IN_PROFILE_YAMLS: &[&str] = &[ include_str!("../../../providers/claude.yaml"), include_str!("../../../providers/codex.yaml"), include_str!("../../../providers/copilot.yaml"), + include_str!("../../../providers/docker-agent.yaml"), include_str!("../../../providers/github.yaml"), include_str!("../../../providers/gitlab.yaml"), include_str!("../../../providers/nvidia.yaml"), diff --git a/crates/openshell-providers/src/providers/docker_agent.rs b/crates/openshell-providers/src/providers/docker_agent.rs new file mode 100644 index 000000000..2a03189ae --- /dev/null +++ b/crates/openshell-providers/src/providers/docker_agent.rs @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + ProviderDiscoverySpec, ProviderError, ProviderPlugin, RealDiscoveryContext, discover_with_spec, +}; + +pub struct DockerAgentProvider; + +pub const SPEC: ProviderDiscoverySpec = ProviderDiscoverySpec { + id: "docker-agent", + credential_env_vars: &["DOCKER_ACCESS_TOKEN"], +}; + +impl ProviderPlugin for DockerAgentProvider { + fn id(&self) -> &'static str { + SPEC.id + } + + fn discover_existing(&self) -> Result, ProviderError> { + discover_with_spec(&SPEC, &RealDiscoveryContext) + } + + fn credential_env_vars(&self) -> &'static [&'static str] { + SPEC.credential_env_vars + } +} + +#[cfg(test)] +mod tests { + use super::SPEC; + use crate::discover_with_spec; + use crate::test_helpers::MockDiscoveryContext; + + #[test] + fn discovers_docker_agent_hub_token() { + let ctx = + MockDiscoveryContext::new().with_env("DOCKER_ACCESS_TOKEN", "dckr_pat_test_token"); + let discovered = discover_with_spec(&SPEC, &ctx) + .expect("discovery") + .expect("provider"); + assert_eq!( + discovered.credentials.get("DOCKER_ACCESS_TOKEN"), + Some(&"dckr_pat_test_token".to_string()) + ); + } +} diff --git a/crates/openshell-providers/src/providers/mod.rs b/crates/openshell-providers/src/providers/mod.rs index 6fe395135..ad2fac967 100644 --- a/crates/openshell-providers/src/providers/mod.rs +++ b/crates/openshell-providers/src/providers/mod.rs @@ -5,6 +5,7 @@ pub mod anthropic; pub mod claude; pub mod codex; pub mod copilot; +pub mod docker_agent; pub mod generic; pub mod github; pub mod gitlab; diff --git a/providers/docker-agent.yaml b/providers/docker-agent.yaml new file mode 100644 index 000000000..c4fb4e17a --- /dev/null +++ b/providers/docker-agent.yaml @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +id: docker-agent +display_name: Docker Agent +description: Docker AI agent runner (docker agent) +category: agent +inference_capable: false +credentials: + - name: hub_token + description: Docker Hub token for pulling agent images from OCI registries + env_vars: [DOCKER_ACCESS_TOKEN] + required: false + auth_style: bearer + header_name: authorization +endpoints: + - host: registry-1.docker.io + port: 443 + protocol: rest + access: read-only + enforcement: enforce + - host: hub.docker.com + port: 443 + protocol: rest + access: read-only + enforcement: enforce + - host: model-runner.docker.internal + port: 80 + protocol: rest + access: read-write + enforcement: enforce +binaries: [/usr/bin/docker, /usr/local/bin/docker, /usr/bin/docker-agent, /usr/local/bin/docker-agent]