Podium uses S3 as a shared deployment registry, enabling on-demand agent deployment across a distributed coordinator cluster.
S3 Bucket Structure
s3://podium-deployment-registry/
{environment}/
deployments/
{agent_type}/
{version}/
{agent_type}-{version}.tar.gz
Example:
s3://podium-prod/
production/
deployments/
claude-agent/
1.0.0/
claude-agent-1.0.0.tar.gz
gpt-agent/
2.5.0/
gpt-agent-2.5.0.tar.gz
Deployment ID Format
{agent_type}:{version}@{hash_prefix}
Example: claude-agent:1.0.0@2b795103
- agent_type: Agent category
- version: Semantic version
- hash_prefix: First 8 chars of SHA256 (content-addressable)
On-Demand Deployment
When a coordinator receives an instance creation request for a deployment it doesn't have locally:
pub async fn ensure_deployment(agent_type: &str, version: &str) -> Result<PathBuf> {
let version_path = self.get_agent_version_path(agent_type, version);
// Fast path: deployment exists locally
if version_path.exists() {
return Ok(version_path);
}
// On-demand path: download from S3 registry
if self.s3_configured() {
self.download_deployment_from_s3(agent_type, version).await?;
return Ok(version_path);
}
Err("Deployment not found locally and S3 not configured")
}
Key properties:
- Lazy deployment: Only download when an instance is requested
- Local caching: Already-deployed agents use the local copy
- Consistency: All coordinators deploy from the same S3 source
- Checksum verification: SHA256 integrity check on download
S3 Client Configuration
Supports both AWS S3 and MinIO:
let s3_client = if let Ok(endpoint_url) = std::env::var("AWS_ENDPOINT_URL") {
// MinIO configuration
let s3_config = aws_sdk_s3::config::Builder::from(&config)
.endpoint_url(endpoint_url)
.force_path_style(true) // Required for MinIO
.build();
S3Client::from_conf(s3_config)
} else {
// Standard AWS S3
S3Client::new(&config)
};
Upload Flow
Developer/CI
│
│ tar.gz bundle (multipart upload)
▼
Gateway POST /api/v1/deployments
│
├── Compute SHA256 checksum
├── Upload to S3: {env}/deployments/{type}/{version}/{bundle}
├── Generate deployment_id
├── Forward to coordinator: POST /deploy/agent
│
└── Return deployment_id to client