@inference-gateway/adl-cli
v0.45.1
Published
Scaffold complete A2A (Agent-to-Agent) projects from YAML Agent Definition Language (ADL) manifests. Thin npm wrapper around the native adl binary.
Downloads
1,024
Maintainers
Readme
ADL CLI
A command-line interface for generating enterprise-ready A2A (Agent-to-Agent) servers from Agent Definition Language (ADL) files.
⚠️ Early Development Warning: This project is in its early stages of development. Breaking changes are expected and acceptable until we reach a stable version. Use with caution in production environments.
Table of Contents
- Overview
- Installation
- Quick Start
- Usage
- Agent Definition Language (ADL)
- Generated Project Structure
- Sandbox Environments
- Enterprise Features
- Artifacts Support
- GitHub Issue Templates
- Examples
- Template System & Architecture
- Customizing Generation with .adl-ignore
- Configurable Acronyms
- Post-Generation Hooks
- Development
- Roadmap
- License
- Support
Overview
The ADL CLI helps you build enterprise-ready A2A agents quickly by generating complete project scaffolding from YAML-based Agent Definition Language (ADL) files. It eliminates boilerplate code and ensures consistent patterns across your agent implementations.
Key Features
- 🚀 Rapid Development - Generate complete projects in seconds
- 📋 Schema-Driven - Use YAML Agent Definition Language files (ADL) to define your agents
- 🎯 Enterprise Ready - Single unified template with AI integration and enterprise features
- 🔐 Enterprise Features - Authentication, SCM integration, and audit logging
- 🛠️ Smart Ignore - Protect your implementations with .adl-ignore files
- ✅ Validation - Built-in ADL schema validation
- 🛠️ Interactive Setup - Guided project initialization with extensive CLI options
- 🔗 Structured Services - Type-safe dependency injection with interfaces and factory functions
- ⚙️ Configuration Management - Automatic environment variable mapping with proper naming conventions
- 🔧 CI/CD Generation - Automatic GitHub Actions workflows with semantic-release CD pipelines
- 🏗️ Sandbox Environments - Flox and DevContainer support for isolated development
- 🎣 Post-Generation Hooks - Customize build, format, and test commands after generation
- 🤖 Multi-Provider AI - OpenAI, Anthropic, Google, Groq, Mistral, DeepSeek, Cohere, Cloudflare, Moonshot, Ollama, Ollama Cloud, and Nvidia support
- 📁 Artifacts Support - Integrated filesystem and MinIO object storage for artifact management
Installation
npm / npx (Recommended)
Most developers already have Node.js - run adl without a prior install via
@inference-gateway/adl-cli,
a thin wrapper that downloads the matching native binary on first use:
npx @inference-gateway/adl-cli init my-agent
npx @inference-gateway/adl-cli generate --file agent.yaml --output ./agent
npx @inference-gateway/adl-cli validate agent.yamlOr install it globally:
npm install -g @inference-gateway/adl-cli
adl --helpPrebuilt binaries are available for Linux and macOS on x64/arm64. The npm package version tracks the native binary version one-to-one.
Install Script
Use our install script to automatically download and install the latest binary:
curl -fsSL https://raw.githubusercontent.com/inference-gateway/adl-cli/main/install.sh | bashOr download and run the script manually:
wget https://raw.githubusercontent.com/inference-gateway/adl-cli/main/install.sh
chmod +x install.sh
./install.shInstall Options:
- Install specific version:
./install.sh --version v1.0.0 - Custom install directory:
INSTALL_DIR=~/bin ./install.sh - Show help:
./install.sh --help
From Source
git clone https://github.com/inference-gateway/adl-cli.git
cd adl-cli
go install .Using Go Install
go install github.com/inference-gateway/adl-cli@latestNix Flake
Run the latest version directly without installing:
nix run github:inference-gateway/adl-cliOr pin a specific version:
nix run github:inference-gateway/adl-cli/v0.41.3Build and add it to your profile:
nix profile install github:inference-gateway/adl-cli/v0.41.3Enter a development shell with go, go-task, golangci-lint, gopls, and
goreleaser available:
nix develop github:inference-gateway/adl-cliFlox
Pin adl to a specific version inside a Flox environment by
adding it to your .flox/env/manifest.toml:
[install]
adl.flake = "github:inference-gateway/adl-cli/v0.41.3"Then activate the environment:
flox activatePre-built Binaries
Download pre-built binaries from the releases page.
Quick Start
1. Initialize a New Project
# Interactive project setup - creates ADL manifest
adl init my-weather-agent
# Generate project code from the manifest
adl generate --file agent.yaml --output ./test-my-agent2. Implement Your Business Logic
The generated project includes TODO placeholders for your implementations:
// TODO: Implement weather API logic
func GetWeatherTool(ctx context.Context, args map[string]any) (string, error) {
city := args["city"].(string)
// TODO: Replace with actual weather API call
return fmt.Sprintf(`{"city": "%s", "temp": "22°C"}`, city), nil
}3. Build and Run
cd test-weather-agent
task build
task runUsage
Commands
| Command | Description |
| --------------------- | ------------------------------------------------------------------ |
| adl init [name] | Create ADL manifest file interactively with options |
| adl generate | Generate project code from ADL file with CI/CD and sandbox support |
| adl validate [file] | Validate an ADL file against the complete schema |
Init Command
The adl init command provides a interactive wizard for creating ADL manifest files:
# Interactive ADL manifest creation
adl init my-weather-agent
# Use defaults for all prompts
adl init my-agent --defaults
# Non-interactive with specific configuration
adl init my-agent \
--name "Weather Agent" \
--description "Provides weather information" \
--provider deepseek \
--model deepseek-v4-flash \
--language go \
--floxInit Command Options
The init command supports extensive configuration options:
Project Settings:
--defaults- Use default values for all prompts--path- Project directory path--name- Agent name--description- Agent description--version- Agent version
Agent Configuration:
--type- Agent type (ai-powered/minimal)--provider- AI provider (openai/anthropic/google/groq/mistral/deepseek/cohere/cloudflare/moonshot/ollama/ollama_cloud/nvidia/minimax)--model- AI model name--system-prompt- System prompt for the agent--max-tokens- Maximum tokens (integer)--temperature- Temperature (0.0-2.0)
Capabilities:
--streaming- Enable streaming responses--notifications- Enable push notifications--history- Enable state transition history
Server Configuration:
--port- Server port (integer)--debug- Enable debug mode
Language-Specific Options:
--language- Programming language (go/rust/typescript)
Go Options:
--go-module- Go module path (e.g.,github.com/user/project)--go-version- Go version (e.g.,1.26.2)
Rust Options:
--rust-package-name- Rust package name--rust-version- Rust version (e.g.,1.94)--rust-edition- Rust edition (e.g.,2024)
TypeScript Options:
--typescript-name- TypeScript package name
Environment Options:
--flox- Enable Flox environment--devcontainer- Enable DevContainer environment
Pipeline / AI Options (declarative, written into the manifest as false by default):
--ai- Shortcut for the init wizard: writesspec.development.ai.orchestrators.claudecode.enabled: trueinto the generatedagent.yaml. Every other per-agent toggle (codex,gemini,opencode,infer) stays off; editagent.yamlafter init to enable additional agents (see Per-agent AI assistants).--ci- Setsspec.scm.ci: true(generate CI workflow onadl generate)--cd- Setsspec.scm.cd: true(generate CD pipeline + semantic-release onadl generate)
Generate Command
# Generate project from ADL file
adl generate --file agent.yaml --output ./test-my-agent
# Overwrite existing files (respects .adl-ignore)
adl generate --file agent.yaml --output ./test-my-agent --overwrite
# Generate with CI workflow configuration
adl generate --file agent.yaml --output ./test-my-agent --ci
# Generate with CloudRun deployment configuration
adl generate --file agent.yaml --output ./test-my-agent --deployment cloudrun
# Generate with CloudRun deployment and CD pipeline
adl generate --file agent.yaml --output ./test-my-agent --deployment cloudrun --cdGenerate Flags
| Flag | Description |
| ------------------ | ---------------------------------------------------------------------------------- |
| --file, -f | ADL file to generate from (default: "agent.yaml") |
| --output, -o | Output directory for generated code (default: ".") |
| --template, -t | Template to use (default: "minimal") |
| --overwrite | Overwrite existing files (respects .adl-ignore) |
| --ci | Generate CI workflow configuration (GitHub Actions). Overrides spec.scm.ci. |
| --cd | Generate CD pipeline configuration with semantic-release. Overrides spec.scm.cd. |
| --deployment | Generate deployment configuration (kubernetes, cloudrun) |
Declarative equivalents:
--ciand--cdare mirrored byspec.scm.ciandspec.scm.cd. The CLI flag is OR'd on top of the manifest value (passing the flag wins; omitting it falls back to the manifest). AI assistants are entirely manifest-driven via the per-agent toggles inspec.development.ai.orchestrators
- see the matrix below.
adl initwrites all toggles asfalseby default - they're opt-in. Generated files (CLAUDE.md,GEMINI.md,AGENTS.md,.github/workflows/ci.yml,.github/workflows/cd.yml,.github/workflows/claude.yml,.github/workflows/codex.yml,.github/workflows/gemini.yml,.releaserc.yaml) are taggedlinguist-generated=truein.gitattributesso they collapse in pull request diffs.
CI Generation Features:
- Automatic Provider Detection: Detects GitHub from ADL
spec.scm.provider(GitLab support planned) - Language-Specific Workflows: Tailored CI configurations for Go, Rust, and TypeScript
- Version Integration: Uses language versions from ADL configuration
- Task Integration: Leverages generated Taskfile for consistent build processes
- Caching: Includes service caching for faster builds
CD Generation Features:
- Semantic Release Integration: Automatic versioning based on conventional commits
- Multi-Language Support: Builds and tests for Go, Rust, and TypeScript projects
- Container Publishing: Builds and pushes Docker images to GitHub Container Registry
- Manual Dispatch: CD workflow triggered manually via GitHub Actions
- Changelog Generation: Automatic CHANGELOG.md generation with release notes
- GitHub Releases: Creates GitHub releases with appropriate tagging
- Deployment Integration: Supports automatic deployment to Kubernetes and Cloud Run after successful releases
AI Integration Features:
The ADL CLI honours the per-agent toggles under
spec.development.ai.orchestrators (the per-agent toggles were introduced in
ADL schema v0.8.0 and moved under orchestrators in adl#27). Each entry is
independent and defaults to false:
spec:
development:
ai:
orchestrators:
claudecode:
enabled: true # generates CLAUDE.md + .github/workflows/claude.yml
codex:
enabled: false # would generate AGENTS.md + .github/workflows/codex.yml
gemini:
enabled: false # would generate GEMINI.md + .github/workflows/gemini.yml
opencode:
enabled: false # would generate AGENTS.md (no upstream action yet)
infer:
enabled: false # would generate AGENTS.md (no upstream action yet)Per-agent AI assistants
| Agent toggle | Docs file the agent reads | GitHub Actions workflow generated? |
| ------------ | ------------------------- | --------------------------------------------------------------------------------- |
| claudecode | CLAUDE.md | yes (.github/workflows/claude.yml, uses anthropics/claude-code-action) |
| codex | AGENTS.md (shared) | yes (.github/workflows/codex.yml, uses openai/codex-action) |
| gemini | GEMINI.md | yes (.github/workflows/gemini.yml, uses google-github-actions/run-gemini-cli) |
| opencode | AGENTS.md (shared) | no upstream action yet - docs only |
| infer | AGENTS.md (shared) | no workflow scaffolded yet - docs only |
AGENTS.mdis generated once and is shared by every enabled agent that reads from it (codex,opencode,infer); the file's contents are agent-agnostic.CLAUDE.mdandGEMINI.mdare agent-specific and only appear when the matching toggle is on.- If no toggles are enabled, no AI docs or workflows are emitted.
- Pre-v0.8.0 manifests using
spec.development.ai.enabled: true, and the flat per-agent shapespec.development.ai.<agent>(pre-orchestrators), are no longer accepted -adl validateandadl generatefail with a migration hint pointing atspec.development.ai.orchestrators. Move the toggle to the specific agent you want (e.g.orchestrators.claudecode.enabled: true). - When
claudecodeis enabled, sandbox environments (Flox, DevContainer) also gain theclaude-codeCLI / extension automatically.
Deployment Generation Features:
The --deployment flag generates platform-specific deployment configurations:
- CloudRun Deployment: Creates a
deploytask in the rootTaskfile.ymlfor gcloud deployment- Supports both Google Container Registry (GCR) and GitHub Container Registry (GHCR)
- Configurable resources (CPU, memory), scaling (min/max instances), and service options
- Uses direct gcloud commands for truly serverless deployment (no Kubernetes required)
- Automatic container building with Docker or Cloud Build integration
- Kubernetes Deployment: Creates
k8s/deployment.yamlwith standard Kubernetes manifests- Enterprise-ready configurations with resource limits and health checks
- ConfigMap and Secret integration for environment variables
- Service and Ingress configurations for load balancing
Agent Definition Language (ADL)
ADL files use YAML to define your agent's configuration, capabilities, and tools.
The canonical schema lives in the inference-gateway/adl repository - that repo is the single source of truth for the ADL specification. This CLI vendors a pinned copy at internal/schema/schema.json (refresh with task fetch-schema).
Example ADL File
apiVersion: adl.inference-gateway.com/v1
kind: Agent
metadata:
name: weather-agent
description: "Provides weather information for cities worldwide"
version: "1.0.0"
spec:
capabilities:
streaming: true
pushNotifications: false
stateTransitionHistory: false
agent:
provider: "" # Choose: openai, anthropic, google, groq, mistral, deepseek, cohere, cloudflare, moonshot, ollama, ollama_cloud, nvidia, minimax
model: "" # Specify default model name for chosen provider
systemPrompt: "You are a helpful weather assistant."
maxTokens: 4096
temperature: 0.7
tools:
- name: get_weather
description: "Get current weather for a city"
schema:
type: object
properties:
city:
type: string
description: "City name"
country:
type: string
description: "Country code"
required:
- city
server:
port: 8080
debug: false
language:
go:
module: "github.com/example/weather-agent"
version: "1.26.2"
acronyms: # Optional: Custom acronyms for better code generation
- api
- json
- xmlADL Schema
The complete ADL schema includes:
- metadata: Agent name, description, and version
- capabilities: Streaming, notifications, state history
- config: Structured configuration sections with environment variable mapping
- services: Service services with interfaces, factories, and type definitions
- agent: AI provider configuration (OpenAI, Anthropic, Google, Groq, Mistral, DeepSeek, Cohere, Cloudflare, Moonshot, Ollama, Ollama Cloud, Nvidia)
- tools: Function-call definitions with JSON schemas, validation, and service injection support
- skills: Markdown playbooks (id + optional
bare, version, source) pulled from the skills registry, fetched as a full directory from a GitHub repo (shorthand or URL), or scaffolded locally; advertised on the agent card and prepended to the system prompt at runtime - server: HTTP server configuration with authentication support
- language: Programming language-specific settings (Go, Rust, TypeScript) and configurable acronyms
- scm: Source control management configuration (GitHub, GitLab)
- sandbox: Development environment configuration (Flox, DevContainer)
- deployment: Platform-specific deployment configuration (Kubernetes, Cloud Run)
Complete ADL Example
apiVersion: adl.inference-gateway.com/v1
kind: Agent
metadata:
name: advanced-agent
description: "Enterprise agent with full feature set"
version: "1.0.0"
spec:
capabilities:
streaming: true
pushNotifications: true
stateTransitionHistory: true
agent:
provider: deepseek
model: deepseek-v4-flash
systemPrompt: |
You are a helpful assistant with enterprise capabilities.
Always prioritize security and compliance.
maxTokens: 8192
temperature: 0.3
config:
database:
connectionString: "postgresql://user:pass@localhost:5432/db"
maxConnections: "10"
timeout: "30s"
notifications:
slackWebhook: "https://hooks.slack.com/services/..."
emailApiKey: "your-email-api-key"
retryAttempts: "3"
services:
database:
type: service
interface: DatabaseService
factory: NewDatabaseService
description: PostgreSQL database service for persistent storage
notifications:
type: service
interface: NotificationService
factory: NewNotificationService
description: Multi-channel notification service
tools:
- name: query_database
description: "Execute database queries with validation"
inject:
- logger
- database
schema:
type: object
properties:
query:
type: string
description: "SQL query to execute"
table:
type: string
description: "Target table name"
limit:
type: integer
description: "Result limit"
maximum: 1000
required:
- query
- table
- name: send_notification
description: "Send multi-channel notifications"
inject:
- logger
- notifications
schema:
type: object
properties:
recipient:
type: string
description: "Recipient identifier"
message:
type: string
description: "Message content"
priority:
type: string
enum:
- low
- medium
- high
- critical
channel:
type: string
enum:
- email
- slack
- teams
- webhook
required:
- recipient
- message
- priority
- channel
server:
port: 8443
debug: false
auth:
enabled: true
language:
go:
module: "github.com/company/advanced-agent"
version: "1.26.2"
scm:
provider: github
url: "https://github.com/company/advanced-agent"
deployment:
type: cloudrun
cloudrun:
image:
registry: gcr.io
repository: advanced-agent
tag: latest
useCloudBuild: true
resources:
cpu: "2"
memory: 1Gi
scaling:
minInstances: 1
maxInstances: 100
concurrency: 1000
service:
timeout: 3600
allowUnauthenticated: false
serviceAccount: advanced-agent@PROJECT_ID.iam.gserviceaccount.com
executionEnvironment: gen2
environment:
LOG_LEVEL: info
ENVIRONMENT: production
development:
sandbox:
flox:
enabled: trueExtra dependencies (spec.language.<lang>.vendor)
Every language config block accepts an optional vendor section that lets
the manifest extend the generator's built-in dependency set. Use deps
for runtime/production dependencies and devdeps for development-only
ones. The exact meaning of devdeps depends on the language - see the
mapping table below. Each entry must be <package>@<version> using
the target language's native package and version syntax - the schema
validates the shape up front (^\S+@\S+$) and points at the offending
key if you mistype it (e.g. spec.language.go.vendor.deps.0).
Conflict policy: generator built-ins always win. If your manifest
lists a package that the generator already pins (e.g.
github.com/inference-gateway/adk for Go, tokio for Rust), the
vendor entry is silently dropped and a ⚠️ vendor … collides with
built-in … warning is printed to stderr. This prevents accidental
downgrades of the core runtime SDK.
Output mapping per language:
| Language | deps lands in | devdeps lands in |
| ---------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Go | go.mod require block | go.mod tool directive (executable dev tools: code generators, linters, etc.) plus an // indirect entry in require so the module is downloadable. Test libraries that you import (testify, go-cmp, …) belong in deps, not devdeps. |
| Rust | Cargo.toml [dependencies] | Cargo.toml [dev-dependencies] |
| TypeScript | package.json dependencies | package.json devDependencies |
For Go, supply the full tool package path (the binary's main package,
e.g. golang.org/x/tools/cmd/stringer) with a version. After generation,
run go mod tidy so Go normalises the indirect require entry to the
actual module root.
Examples per language:
# Go: uuid for runtime, stringer + mockgen as dev tools.
spec:
language:
go:
module: github.com/example/agent
version: "1.26.2"
vendor:
deps:
- github.com/google/[email protected]
- github.com/stretchr/[email protected] # imported by *_test.go
devdeps:
- golang.org/x/tools/cmd/[email protected]
- github.com/golang/mock/[email protected]# Rust: regex at runtime, mockall + pretty_assertions for tests.
spec:
language:
rust:
packageName: agent
version: "1.94.1"
edition: "2024"
vendor:
deps:
- [email protected]
devdeps:
- [email protected]
- [email protected]# TypeScript: axios at runtime, vitest + @types/node for tests.
spec:
language:
typescript:
packageName: "@example/agent"
nodeVersion: "20"
vendor:
deps:
- [email protected]
devdeps:
- "@types/[email protected]"
- [email protected]Extra sandbox dependencies (spec.development.deps)
spec.development.deps is the cross-cutting equivalent of the per-language
vendor.deps block above: it lets you install tools into the development
sandbox (Flox, devcontainer) that don't belong to any single language's
package manager. Use it for things like deno, kubectl, terraform,
awscli, or any other CLI you want available inside the dev shell. Each
entry follows the <package>@<version> shape, validated up front by the
schema (^\S+@\S+$).
spec:
development:
sandbox:
flox:
enabled: true
devcontainer:
enabled: true
deps:
- deno@^2.7.14
- kubectl@^1.36.1
- terraform@^1.15.3Merge semantics: additive. The per-language toolchain that each
sandbox template already installs (go/cargo/nodejs, plus git,
docker, go-task) is always emitted; spec.development.deps entries
are appended on top, sorted alphabetically so the generated file diffs
stay stable on re-run. Duplicate package names inside deps are deduped
(first occurrence wins on version). When a deps entry's package name
collides with one of the template's built-ins (e.g. [email protected]), the
generator prints a ⚠️ spec.development.deps … collides with a Flox
built-in … warning to stderr but still renders the user entry - the
maintainer's pin wins on version conflict.
Output mapping per backend:
| Backend | Generated file | Per-entry rendering |
| --------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| flox | .flox/env/manifest.toml | A pair of TOML lines under [install]: <pkg>.pkg-path = "<pkg>" / <pkg>.version = "<version>". Resolved against Nixpkgs at activation time. |
| devcontainer | .devcontainer/devcontainer.json | Added to the features block as ghcr.io/devcontainers-extra/features/apt-packages:1 with the comma-joined <pkg>=<version> list. Resolution is best-effort against apt. |
| dockerCompose | (out of scope for this release; see issue #154) | n/a |
If a package isn't published under its short attribute path in Nixpkgs,
or isn't available as an apt package on the devcontainer base image,
add the file to your project's .adl-ignore and hand-author the
override - this is the same escape hatch we use for any sandbox file
the template can't infer.
Worked example per backend:
# Flox: pin deno + kubectl + terraform alongside the Go toolchain
spec:
language:
go: { module: github.com/example/agent, version: "1.26.2" }
development:
sandbox:
flox:
enabled: true
deps:
- [email protected]
- [email protected]
- [email protected]# Devcontainer: same deps, rendered as an apt-packages feature
spec:
language:
go: { module: github.com/example/agent, version: "1.26.2" }
development:
sandbox:
devcontainer:
enabled: true
deps:
- [email protected]
- [email protected]Skills vs. Tools
The ADL spec distinguishes two complementary concepts:
- Tools (
spec.tools) are function-call entrypoints with explicit JSON schemas. They are generated as code in the target language and registered with the agent's toolbox. The model invokes them by name with structured arguments. - Skills (
spec.skills) are markdown playbooks (with YAML frontmatter) that describe when and how to use the tools. Each is written to its own directory atskills/<id>/SKILL.mdin the generated project, advertised on the agent card so orchestrators can discover them, and prepended to the system prompt at runtime. The directory layout matches Anthropic's agent skills convention - bare skills can ship arbitrary scripts, templates, or reference material alongsideSKILL.md.
A skill entry is small:
spec:
skills:
- id: data-analysis # pulled from registry.inference-gateway.com/skills/
version: 0.1.0 # optional pin
- id: report-writing # pulled at the default version
- id: company-policy # scaffolded locally (not fetched)
bare: true
name: company-policy
description: "Internal compliance rules to follow"
license: Proprietary # optional SPDX id or "Proprietary"
tags: [policy, compliance]
- id: pdf # pull a full skill directory from GitHub
source: anthropics/skills/pdf
- id: skill-creator
source: [email protected] # pin to a tag/branch/shaResolution rules
bare: true→ the CLI scaffoldsskills/<id>/SKILL.mdwith frontmatter from the manifest and a TODO body that you author by hand. The wholeskills/<id>/directory is listed in.adl-ignore, so any bundled scripts, templates, or resources you drop alongsideSKILL.mdare preserved on regeneration.source:set → the source must resolve to a public GitHub directory (a/tree/<ref>/<path>URL, or one of the shorthand forms below). The CLI pulls the entire directory -SKILL.md, reference docs, bundled scripts, anything else - and writes it toskills/<id>/. Non-github.comURLs are rejected so the same code path always produces a complete skill bundle, not a stray markdown file.- Otherwise → fetch
https://registry.inference-gateway.com/skills/<id>[/<version>].md(becomesskills/<id>/SKILL.md). Override the registry withADL_SKILLS_REGISTRY. Registry-by-id currently shipsSKILL.mdonly; if you need bundled assets, usesource:to point at a GitHub directory.
Licensing
license is optional on every skill entry. When set, it must be one of the
SPDX identifiers enumerated in the schema (MIT, Apache-2.0, BSD-2-Clause,
BSD-3-Clause, GPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, MPL-2.0, ISC,
CC0-1.0, CC-BY-4.0, CC-BY-SA-4.0, Unlicense) or the literal string
Proprietary for closed-source skills. The resolver mirrors the value into the
generated SKILL.md frontmatter so the licence travels with the playbook -
shipping a separate LICENSE file alongside SKILL.md is optional. When the
ADL entry and the fetched frontmatter both set license, the value in the ADL
manifest wins.
Use adl generate --offline to skip network access - every non-bare skill must already be cached at ~/.adl/skills-cache/<id>@<ref>/ (where <ref> is the pinned tag/branch, or latest for an unpinned registry fetch).
source: shorthand grammar
Every form below resolves to a GitHub tree/<ref>/<path> URL. An optional @<tag> suffix pins a branch, tag, or commit SHA; omit it to use the default main branch.
| Shorthand | Expands to |
| --------------------------------- | ----------------------------------------------------------------------- |
| <skill> | https://github.com/inference-gateway/skills/tree/main/skills/<skill> |
| <skill>@<tag> | https://github.com/inference-gateway/skills/tree/<tag>/skills/<skill> |
| <owner>/<repo>/<skill> | https://github.com/<owner>/<repo>/tree/main/skills/<skill> |
| <owner>/<repo>/<skill>@<tag> | https://github.com/<owner>/<repo>/tree/<tag>/skills/<skill> |
| Full https://github.com/... URL | passed through unchanged |
Concrete examples:
# Default inference-gateway/skills, latest main:
- id: skill-creator
source: skill-creator
# Default inference-gateway/skills, pinned to a tag:
- id: skill-creator
source: [email protected]
# Different repo (Anthropic's official skill library):
- id: pdf
source: anthropics/skills/pdf
# Different repo, pinned to a commit SHA:
- id: pdf
source: anthropics/skills/pdf@abc1234
# Full URL for anything that doesn't fit the shorthand:
- id: custom
source: https://github.com/my-org/my-repo/tree/release/path/to/skillThe 3-segment form assumes a skills/<id>/ subdirectory inside the repo (the convention used by both inference-gateway/skills and anthropics/skills). If your repo lays skills out differently, pass the full URL.
Runtime: AVAILABLE SKILLS manifest + on-demand Read
The generated agent advertises skills to the LLM via a frontmatter-only manifest, not by inlining SKILL.md bodies. At startup it walks first-level subdirectories under skills/ (overridable with A2A_SKILLS_DIR), parses each <id>/SKILL.md's YAML frontmatter, and appends an AVAILABLE SKILLS: block to the system prompt:
AVAILABLE SKILLS:
Skills are reusable instructions for specific tasks. When a task matches a
skill's description, read the SKILL.md file at the listed path using the Read
tool, then follow its instructions.
- incident-response: Use this when the user reports a production incident...
Path: skills/incident-response/SKILL.md
- pdf: Fill in PDF forms and extract structured data from PDFs.
Path: skills/pdf/SKILL.mdThe model loads each SKILL.md body on demand via the Read built-in tool, and executes any bundled scripts via Bash / Write / Edit. A skills-using agent must therefore list - id: read in spec.tools and set spec.config.tools.read.enabled: true - the validator enforces this; see Reserved built-in tools.
Reserved built-in tools
spec.tools accepts five reserved IDs that map to framework-supplied implementations:
| Reserved ID | Generated as | Purpose |
| ----------- | --------------------- | ------------------------------------------------------------------------------------- |
| read | tools/read.go etc. | Read a file (file_path, optional offset/limit). |
| bash | tools/bash.go etc. | Execute a shell command (subject to whitelist + timeout). |
| write | tools/write.go etc. | Write content to a file (creates parent dirs). |
| edit | tools/edit.go etc. | Replace a unique string in a file (old_string → new_string). |
| fetch | tools/fetch.go etc. | Fetch an http(s) URL (whitelist, max-bytes cap, optional save-to-disk inside /tmp). |
Opt in by listing the id alone - the generator owns name, description, and the JSON schema:
spec:
tools:
- id: read
- id: bash
- id: query_database # user tool: full entry still required
name: query_database
description: "..."
schema: { type: object, ... }All five built-ins default to enabled: false. Activate them via the reserved namespace spec.config.tools.<id>:
spec:
config:
tools:
read:
enabled: true
max_lines: 2000 # offset/limit default window
allowed_roots: [] # empty = project-wide
bash:
enabled: true
whitelist: [ls, cat, grep, jq]
timeout_seconds: 30
write:
enabled: false # listed but explicitly disabled
edit:
enabled: true
fetch:
enabled: true
allowed_domains: # whitelist of hosts (empty = unrestricted, discouraged)
- example.com
- .api.dev # entries starting with "." match any subdomain
max_bytes: 10485760 # 10 MiB cap on response body (default)
timeout_seconds: 30 # total request timeout (default)
download_dir: /tmp # root for save_path writes (default /tmp)
allow_downloads: false # set true to allow writing response bodies to diskValues are baked into the generated constructor as compile-time literals - there's no ToolsConfig struct in config/config.go because reserved-namespace sections are intentionally skipped. The validator decodes each spec.config.tools.<id> block into the built-in's typed shape and rejects unknown keys (typos like tymeout_seconds fail with spec.config.tools.bash.tymeout_seconds).
Runtime overrides for Bash (read inside tools/bash.go):
A2A_BASH_DISABLED=1is a kill switch - overridesenabled: trueback to false.A2A_BASH_WHITELIST=ls,cat,grepoverrides the compile-time whitelist.
Runtime overrides for Fetch (resolution precedence: env > compile-time literal > default-disabled):
- Go:
TOOLS_FETCH_ENABLED,TOOLS_FETCH_ALLOWED_DOMAINS,TOOLS_FETCH_MAX_BYTES,TOOLS_FETCH_TIMEOUT_SECONDS,TOOLS_FETCH_DOWNLOAD_DIR,TOOLS_FETCH_ALLOW_DOWNLOADS(envconfig-style; comma-separated for lists). - Rust:
A2A_FETCH_DISABLED=1(kill switch),A2A_FETCH_ALLOWED_DOMAINS,A2A_FETCH_MAX_BYTES,A2A_FETCH_TIMEOUT_SECONDS,A2A_FETCH_DOWNLOAD_DIR,A2A_FETCH_ALLOW_DOWNLOADS.
The Fetch tool supports GET and HEAD only. Optional save_path writes the response body to a path resolved under download_dir - absolute paths and parent-directory traversal (..) are rejected, and the request fails unless allow_downloads: true. Bodies (and on-disk files) are capped at max_bytes; oversized responses are truncated and the result payload sets "truncated": true. The Go template uses only the standard library (net/http); the Rust template adds reqwest (rustls-tls + json features) to Cargo.toml automatically when - id: fetch is present in spec.tools.
Resolution precedence at runtime: env > compile-time literal > built-in default (disabled).
Service Injection & Configuration Management
The ADL CLI provides a sophisticated service injection system with structured configuration management. This system improves testability, separation of concerns, and provides type-safe configuration with environment variable mapping.
Structured Service System
Define services with explicit types, interfaces, and factory functions. The system supports both built-in services (like logger) and custom service services:
spec:
config:
googleCalendar:
scopes: "https://www.googleapis.com/auth/calendar"
credentialsPath: "/secrets/credentials.json"
cache:
ttl: "3600"
maxEntries: "1000"
services:
googleCalendar:
type: service
interface: CalendarService
factory: NewCalendarService
description: Google Calendar API service for managing calendar events
cache:
type: service
interface: CacheRepository
factory: NewCacheRepository
description: High-performance caching layer for API responses
tools:
- name: create_event
description: "Create a new calendar event"
inject:
- logger # Built-in, always available
- googleCalendar # Custom service
- cache # Custom service
schema:
type: object
properties:
title:
type: string
description: "Event title"
start:
type: string
description: "Start time (ISO 8601)"
required: [title, start]Configuration Management
The configuration system generates type-safe structs with automatic environment variable mapping:
Generated Configuration (config/config.go):
type Config struct {
// Core application settings
Environment string `env:"ENVIRONMENT"`
// A2A configuration
A2A serverConfig.Config `env:",prefix=A2A_"`
// Custom configuration sections
Cache CacheConfig `env:",prefix=CACHE_"`
GoogleCalendar GoogleCalendarConfig `env:",prefix=GOOGLE_CALENDAR_"`
}
type GoogleCalendarConfig struct {
CredentialsPath string `env:"CREDENTIALS_PATH"`
Scopes string `env:"SCOPES"`
}
type CacheConfig struct {
MaxEntries string `env:"MAX_ENTRIES"`
Ttl string `env:"TTL"`
}Environment Variables:
GOOGLE_CALENDAR_CREDENTIALS_PATH="/secrets/google-creds.json"GOOGLE_CALENDAR_SCOPES="https://www.googleapis.com/auth/calendar"CACHE_MAX_ENTRIES="1000"CACHE_TTL="3600"
Config Subsection Injection
In addition to injecting entire configuration objects, you can inject specific config subsections directly into skills using dotted notation. This provides type-safe access to focused configuration scopes.
Example ADL Configuration:
spec:
config:
database:
connectionString: "postgresql://localhost:5432/db"
maxConnections: "10"
timeout: "30s"
email:
apiKey: ""
fromAddress: "[email protected]"
provider: "sendgrid"
services:
database:
type: service
interface: DatabaseService
factory: NewDatabaseService
description: PostgreSQL database service
tools:
- name: export_report
description: "Export data and email report"
inject:
- logger
- database
- config.email # Inject only the email config subsection
schema:
type: object
properties:
recipient:
type: string
required: [recipient]Generated Skill Code:
type ExportReportSkill struct {
logger *zap.Logger
database database.DatabaseService
email *config.EmailConfig // Type-safe access to email config only
}
func NewExportReportSkill(
logger *zap.Logger,
database database.DatabaseService,
email *config.EmailConfig,
) server.Tool {
skill := &ExportReportSkill{
logger: logger,
database: database,
email: email,
}
// ...
}
func (s *ExportReportSkill) ExportReportHandler(ctx context.Context, args map[string]any) (string, error) {
// Direct access to email config subsection
apiKey := s.email.APIKey
fromAddress := s.email.FromAddress
provider := s.email.Provider
// ... implementation
}Main Registration:
// In main.go - config subsection is passed directly
exportReportSkill := skills.NewExportReportSkill(l, databaseSvc, &cfg.Email)
toolBox.AddTool(exportReportSkill)Benefits of Config Subsection Injection:
- Scoped Access: Skills only receive the configuration they need, following principle of least privilege
- Type Safety: Compile-time validation ensures config fields exist
- Clear Dependencies: Explicit declaration of which config sections each skill requires
- Easier Testing: Mock specific config subsections without full config object
- Better Separation: Skills don't have access to unrelated configuration
- Auto-Validation: ADL CLI validates that injected config sections exist in
spec.config
Injection Patterns:
inject:
- logger # Built-in logger service
- config # Entire config object (*config.Config)
- config.database # Database config subsection (*config.DatabaseConfig)
- config.email # Email config subsection (*config.EmailConfig)
- myService # Custom service from spec.servicesService Architecture
The service injection system generates:
- Built-in Logger: Automatically available as
*zap.Loggerwithout declaration - Type-Safe Configuration: Structured config with environment variable mapping
- Service Interfaces: Custom service packages with interface definitions
- Factory Functions: Constructor functions that receive logger and configuration
- Automatic Registration: Services are automatically wired into skills
- File Protection: Generated service files are automatically added to
.adl-ignore
Generated Structure
my-agent/
├── config/
│ └── config.go # Type-safe configuration with env mapping
├── internal/
│ ├── logger/
│ │ └── logger.go # Built-in logger factory
│ ├── googleCalendar/
│ │ └── googleCalendar.go # Calendar service with interface
│ └── cache/
│ └── cache.go # Cache service with interface
├── tools/
│ ├── create_event.go # Function-call tools with injected services
│ └── list_events.go
├── skills/
│ ├── calendar-workflow/ # Markdown playbooks loaded into the system prompt
│ │ └── SKILL.md
│ └── meeting-summary/
│ └── SKILL.md
└── .adl-ignore # Protects custom implementationsGenerated Service Code
Each service generates a package with interface and factory:
Example internal/googleCalendar/googleCalendar.go:
type CalendarService interface {
// TODO: Define your CalendarService interface methods
CreateEvent(ctx context.Context, event *Event) error
ListEvents(ctx context.Context, query *Query) ([]*Event, error)
}
type calendarService struct {
logger *zap.Logger
config *config.Config
}
func NewCalendarService(logger *zap.Logger, cfg *config.Config) (CalendarService, error) {
// TODO: Implement CalendarService initialization
return &calendarService{
logger: logger,
config: cfg,
}, nil
}Skill Integration
Skills automatically receive injected services as constructor parameters:
Example skills/create_event.go:
type CreateEventSkill struct {
logger *zap.Logger
calendar googleCalendar.CalendarService
cache cache.CacheRepository
}
func NewCreateEventSkill(logger *zap.Logger, calendar googleCalendar.CalendarService, cache cache.CacheRepository) *CreateEventSkill {
return &CreateEventSkill{
logger: logger,
calendar: calendar,
cache: cache,
}
}Benefits
- Type Safety: Structured configuration with compile-time validation
- Environment Variables: Automatic mapping with proper naming conventions
- Interface-Based Design: Testable services with clear contracts
- Separation of Concerns: Configuration separate from service definitions
- Language Agnostic: Works across Go, Rust, and TypeScript
- Hot Reload: Configuration changes via environment variables
- Security: No secrets in code, environment-based configuration
- Scalability: Easy to add new services and configuration sections
Best Practices
- Configuration: Use environment variables for secrets and environment-specific values
- Interfaces: Define clear interfaces for testability and modularity
- Factory Functions: Initialize services with proper error handling
- Logging: Use the injected logger for consistent log formatting
- Testing: Create mock implementations of service interfaces
- Documentation: Document interface methods and configuration options
Generated Project Structure
The ADL CLI generates project scaffolding tailored to your chosen language:
Go Project Structure
my-go-agent/
├── main.go # Main server setup
├── go.mod # Go module definition
├── config/
│ └── config.go # Centralized application configuration
├── internal/
│ └── logger/
│ └── logger.go # Built-in logger factory
├── tools/ # Function-call tool implementations
│ ├── query_database.go # Individual tool files (TODO placeholders)
│ └── send_notification.go
├── skills/ # Skill directories (SKILL.md + optional bundled assets)
│ ├── incident-response/ # Loaded into the system prompt at startup
│ │ └── SKILL.md
│ └── support-handoff/
│ └── SKILL.md
├── Taskfile.yml # Development tasks (build, test, lint)
├── Dockerfile # Container configuration
├── .adl-ignore # Files to protect from regeneration
├── .well-known/
│ └── agent-card.json # Agent capabilities (auto-generated)
├── .github/ # GitHub-specific configurations
│ ├── workflows/ # Generated when using --ci flag
│ │ ├── ci.yml # GitHub Actions CI workflow
│ │ └── cd.yml # GitHub Actions CD workflow (with --cd flag)
│ ├── dependabot.yml # Generated when scm.dependabot: true
│ └── ISSUE_TEMPLATE/ # Generated when issue_templates: true
│ ├── bug_report.md # Bug report template
│ ├── feature_request.md # Feature request template
│ └── refactor_request.md # Refactoring request template
├── .releaserc.yaml # Semantic-release configuration (with --cd flag)
├── k8s/
│ └── deployment.yaml # Kubernetes deployment manifest
├── cloudrun/
│ └── deploy.sh # CloudRun deployment script (with --deployment cloudrun)
├── .flox/ # Generated when sandbox: flox
│ ├── env/manifest.toml
│ ├── env.json
│ ├── .gitignore
│ └── .gitattributes
├── .gitignore # Standard Git ignore patterns
├── .gitattributes # Git attributes configuration
├── .editorconfig # Editor configuration
├── CLAUDE.md # AI assistant instructions (spec.development.ai.orchestrators.claudecode.enabled: true)
└── README.md # Project documentation with setup instructionsRust Project Structure
my-rust-agent/
├── src/
│ ├── main.rs # Main application entry point
│ └── tools/ # Function-call tool implementations
│ ├── mod.rs # Module declarations
│ ├── query_database.rs # Individual tool implementations
│ └── send_notification.rs
├── skills/ # Skill directories (SKILL.md + optional bundled assets)
│ ├── incident-response/
│ │ └── SKILL.md
│ └── support-handoff/
│ └── SKILL.md
├── Cargo.toml # Rust package configuration
├── Taskfile.yml # Development tasks
├── Dockerfile # Rust-optimized container
├── .adl-ignore # Protection configuration
├── .well-known/
│ └── agent-card.json # Agent capabilities
├── .github/workflows/ # CI configuration (with --ci)
│ ├── ci.yml # Rust-specific CI workflow
│ └── cd.yml # GitHub Actions CD workflow (with --cd flag)
├── .releaserc.yaml # Semantic-release configuration (with --cd flag)
├── k8s/
│ └── deployment.yaml # Kubernetes deployment
├── cloudrun/
│ └── deploy.sh # CloudRun deployment script (with --deployment cloudrun)
├── CLAUDE.md # AI assistant instructions (spec.development.ai.orchestrators.claudecode.enabled: true)
└── README.md # DocumentationTypeScript Project Structure
my-typescript-agent/
├── src/
│ ├── index.ts # Main server setup + background task worker
│ ├── config.ts # Typed configuration loader (env-mapped)
│ ├── logger.ts # Built-in logger factory
│ ├── services/ # Injectable service implementations
│ │ └── database.ts
│ └── tools/ # Function-call tool implementations
│ ├── index.ts # Toolbox wiring
│ ├── query_database.ts # Individual tool implementations (TODO placeholders)
│ └── send_notification.ts
├── skills/ # Skill directories (SKILL.md + optional bundled assets)
│ ├── incident-response/
│ │ └── SKILL.md
│ └── support-handoff/
│ └── SKILL.md
├── package.json # Node package definition + scripts
├── tsconfig.json # TypeScript compiler configuration
├── Taskfile.yml # Development tasks
├── Dockerfile # Node-optimized container
├── .adl-ignore # Protection configuration
├── .well-known/
│ └── agent-card.json # Agent capabilities
├── .github/workflows/ # CI configuration (with --ci)
│ ├── ci.yml # TypeScript-specific CI workflow
│ └── cd.yml # GitHub Actions CD workflow (with --cd flag)
├── .releaserc.yaml # Semantic-release configuration (with --cd flag)
├── k8s/
│ └── deployment.yaml # Kubernetes deployment (with --deployment kubernetes)
├── CLAUDE.md # AI assistant instructions (spec.development.ai.orchestrators.claudecode.enabled: true)
└── README.md # DocumentationUniversal Generated Files
All projects include these essential files regardless of language:
.well-known/agent-card.json- A2A agent discovery and capabilities manifestTaskfile.yml- Unified task runner configuration for build, test, lint, runDockerfile- Language-optimized container configurationk8s/deployment.yaml- Kubernetes deployment manifestdeploytask inTaskfile.yml- CloudRun deployment task (when using--deployment cloudrun).adl-ignore- Protects user implementations from overwrite- CI Workflows - When using
--ciflag, generates GitHub Actions workflows:- GitHub Actions:
.github/workflows/ci.yml - GitLab CI:
.gitlab-ci.yml(planned, not yet implemented)
- GitHub Actions:
- CD Workflows - When using
--cdflag, generates continuous deployment:- GitHub Actions:
.github/workflows/cd.yml - Semantic Release:
.releaserc.yaml
- GitHub Actions:
- Development Environment - Based on
sandboxconfiguration:- Flox:
.flox/directory with environment configuration whensandbox.flox.enabled: true - DevContainer:
.devcontainer/devcontainer.jsonwhensandbox.devcontainer.enabled: true
- Flox:
- AI Assistant Instructions - Per-agent toggles under
spec.development.ai.orchestrators(see Per-agent AI assistants):- CLAUDE.md when
spec.development.ai.orchestrators.claudecode.enabled: true - GEMINI.md when
spec.development.ai.orchestrators.gemini.enabled: true - AGENTS.md (shared) when any of
codex,opencode, orinferis enabled
- CLAUDE.md when
CI Integration
When using the --ci flag, the ADL CLI generates GitHub Actions workflows for your project:
# Generate project with CI workflow
adl generate --file agent.yaml --output ./test-my-agent --ciThis creates a GitHub Actions workflow (.github/workflows/ci.yml) that includes:
- Automated Testing: Runs all tests on every push and pull request
- Code Quality: Format checking and linting
- Multi-Environment: Supports main and develop branches
- Caching: Go module caching for faster builds
- Task Integration: Uses the generated Taskfile for consistent build steps
The generated workflow automatically detects your Go version from the ADL file and configures the appropriate environment.
CD Integration
The ADL CLI can generate continuous deployment (CD) pipelines with semantic release automation:
# Generate project with CD pipeline
adl generate --file agent.yaml --output ./test-my-agent --cdThis creates a complete CD setup including:
.releaserc.yaml- Semantic-release configuration with conventional commits.github/workflows/cd.yml- GitHub Actions CD workflow with manual dispatch
The generated CD pipeline includes:
- Semantic Versioning: Automatic version bumping based on conventional commit messages
- Release Automation: Creates GitHub releases with generated release notes
- Container Publishing: Builds and publishes Docker images to GitHub Container Registry
- Multi-Platform Builds: Supports both AMD64 and ARM64 architectures
- Language Detection: Automatically configures build steps based on your project language
- Change Detection: Only publishes releases when there are changes to release
CD Workflow Features
Manual Trigger: The CD workflow uses workflow_dispatch for controlled releases:
# Trigger via GitHub CLI
gh workflow run cd.yml
# Or trigger via GitHub Actions UIConventional Commits Support: The pipeline recognizes these commit types for versioning:
feat:- Minor version bump (new features)fix:- Patch version bump (bug fixes)refactor:,perf:,ci:,docs:,style:,test:,build:,chore:- Patch version bump
Container Registry: Published images are available at:
ghcr.io/your-org/your-agent:latest
ghcr.io/your-org/your-agent:v1.0.0
ghcr.io/your-org/your-agent:1.0CloudRun Deployment
The ADL CLI provides native support for deploying A2A agents to Google Cloud Run, offering a truly serverless deployment experience without Kubernetes complexity.
CloudRun Configuration
Configure CloudRun deployment in your ADL file:
spec:
deployment:
type: cloudrun
cloudrun:
image:
registry: gcr.io # gcr.io or ghcr.io
repository: my-agent # Repository name
tag: latest # Image tag
useCloudBuild: true # Use Cloud Build or local Docker
resources:
cpu: "2" # CPU allocation (0.1 to 8)
memory: 1Gi # Memory limit (128Mi to 32Gi)
scaling:
minInstances: 0 # Minimum instances (0 to 1000)
maxInstances: 100 # Maximum instances (1 to 1000)
concurrency: 1000 # Max concurrent requests per instance
service:
timeout: 3600 # Request timeout in seconds
allowUnauthenticated: true # Allow public access
serviceAccount: my-agent@PROJECT_ID.iam.gserviceaccount.com
executionEnvironment: gen2 # gen1 or gen2
environment: # Custom environment variables
LOG_LEVEL: info
ENVIRONMENT: productionContainer Registry Options
Google Container Registry (GCR):
image:
registry: gcr.io
repository: my-project/my-agent
useCloudBuild: true # Automatically build and pushGitHub Container Registry (GHCR):
image:
registry: ghcr.io
repository: myorg/my-agent
useCloudBuild: false # Skip Cloud Build, use pre-built imageGenerated Deployment Script
When using --deployment cloudrun, the ADL CLI generates a deploy task in the Taskfile.yml that:
- Validates Environment: Checks for required
PROJECT_IDandREGIONvariables - Container Building: Uses Docker locally or Cloud Build based on configuration
- Direct gcloud Deployment: Uses
gcloud run deployfor serverless deployment - Configuration Summary: Displays all deployment settings for verification
CloudRun Deployment Workflow
# 1. Generate project with CloudRun deployment
adl generate --file agent.yaml --output ./my-agent --deployment cloudrun
# 2. Set required environment variables
export PROJECT_ID="my-gcp-project"
export REGION="us-central1"
# 3. Deploy to CloudRun
cd my-agent
task deployCloudRun with CI/CD
Generate CloudRun deployment with continuous deployment:
adl generate --file agent.yaml --deployment cloudrun --cdThis creates:
- CD Workflow: Automatically deploys to CloudRun after releases
- Environment Integration: Uses GitHub secrets for GCP authentication
- Multi-Environment Support: Deploy to different regions/projects
Required GitHub Secrets:
GCP_SA_KEY: Service account key JSONGCP_PROJECT_ID: Google Cloud project IDGCP_REGION: Deployment region (e.g., us-central1)
CloudRun Benefits
- Truly Serverless: No Kubernetes clusters or infrastructure management
- Auto-Scaling: Scale to zero when idle, scale up automatically under load
- Pay-per-Use: Only pay for actual request processing time
- Global Edge: Deploy to multiple regions with traffic management
- Integrated Monitoring: Built-in logging, metrics, and tracing
- Custom Domains: HTTPS support with automatic SSL certificates
Example ADL Files
The CLI includes CloudRun example files:
# Validate CloudRun examples
adl validate examples/cloudrun-agent.yaml
adl validate examples/cloudrun-ghcr-agent.yaml
# Generate CloudRun projects
adl generate --file examples/cloudrun-agent.yaml --output ./cloudrun-test
adl generate --file examples/cloudrun-ghcr-agent.yaml --output ./ghcr-testCloudflare Workers Deployment
Cloudflare Workers run on the V8-isolate edge runtime and, like Vercel and
unlike Kubernetes/CloudRun, deploy from source via wrangler rather than a
prebuilt container image. This target is TypeScript-only - Workers execute
JS/TS on the edge, so a Go or Rust agent does not produce Worker artifacts.
Cloudflare Configuration
spec:
language:
typescript:
packageName: "my-agent"
nodeVersion: "24"
deployment:
type: cloudflare
cloudflare:
name: my-agent # Worker (script) name
accountId: "${CLOUDFLARE_ACCOUNT_ID}" # prefer a ${VAR} placeholder
compatibilityDate: "2025-01-01" # defaults when omitted
compatibilityFlags:
- nodejs_compat # defaults to [nodejs_compat] when omitted
routes:
- agent.example.com/* # custom routes/domains
workersDev: false # expose on *.workers.dev (omit to keep wrangler's default)
environment: # plain-text wrangler [vars]
LOG_LEVEL: infoGenerated Artifacts
wrangler.toml- rendered from the block (name,main,compatibility_date,compatibility_flags,account_id,workers_dev,routes,[vars]).src/worker.ts- a module-format Worker entrypoint scaffold exporting afetchhandler. It is added to.adl-ignore, so your completed handler survives subsequentadl generateruns.
compatibilityDate defaults to a stable value when omitted, and
compatibilityFlags defaults to nodejs_compat (the scaffold relies on Node.js
API compatibility).
Secrets
Secrets are never written to wrangler.toml. Use ${VAR} placeholders only in
the environment block (plain-text [vars]), and set real secrets out-of-band:
wrangler secret put LLM_API_KEYDeploy
# One-time setup (not installed by the scaffold)
pnpm add -D wrangler @cloudflare/workers-types
# then add "@cloudflare/workers-types" to compilerOptions.types in tsconfig.json
#