| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
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.
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.
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.
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:
git clone https://github.com/inference-gateway/adl-cli.git
cd adl-cli
go install .go install github.com/inference-gateway/adl-cli@latestRun 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.51.2Build and add it to your profile:
nix profile install github:inference-gateway/adl-cli/v0.51.2Enter a development shell with go, go-task, golangci-lint, gopls, and goreleaser available:
nix develop github:inference-gateway/adl-cliPin 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.51.2"Then activate the environment:
flox activateDownload pre-built binaries from the releases page.
# 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-agentThe 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
}cd test-weather-agent
task build
task run| 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 |
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 \
--floxThe init command supports extensive configuration options:
Project Settings:
Agent Configuration:
Capabilities:
Server Configuration:
Language-Specific Options:
Go Options:
Rust Options:
TypeScript Options:
Environment Options:
Pipeline / AI Options (declarative, written into the manifest as false by default):
Deployment Options:
# 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 --cd| 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, vercel, cloudflare (TypeScript-only)) |
| --devcontainer | Enable DevContainer environment |
| --flox | Enable Flox environment |
| --offline | Skip the skills registry; require every non-bare skill to already be in the local cache |
Declarative equivalents: --ci and --cd are mirrored by spec.scm.ci and spec.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 in spec.development.ai.orchestrators
- see the matrix below. adl init writes all toggles as false by 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, .github/workflows/infer.yml, .releaserc.yaml) are tagged linguist-generated=true in .gitattributes so they collapse in pull request diffs.
CI Generation Features:
CD Generation Features:
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 + .github/workflows/infer.yml| 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) | yes (.github/workflows/infer.yml, uses inference-gateway/infer-action) |
Deployment Generation Features: The --deployment flag generates platform-specific deployment configurations:
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).
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.4"
acronyms: # Optional: Custom acronyms for better code generation
- api
- json
- xmlThe complete ADL schema includes:
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.4"
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: trueEvery 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.4"
vendor:
deps:
- github.com/google/uuid@v1.6.0
- github.com/stretchr/testify@v1.10.0 # imported by *_test.go
devdeps:
- golang.org/x/tools/cmd/stringer@v0.20.0
- github.com/golang/mock/mockgen@v1.6.0# Rust: regex at runtime, mockall + pretty_assertions for tests.
spec:
language:
rust:
packageName: agent
version: "1.94.1"
edition: "2024"
vendor:
deps:
- regex@1.10.0
devdeps:
- mockall@0.12.1
- pretty_assertions@1.4.0# TypeScript: axios at runtime, vitest + @types/node for tests.
spec:
language:
typescript:
packageName: "@example/agent"
nodeVersion: "20"
vendor:
deps:
- axios@1.7.0
devdeps:
- "@types/node@20.11.0"
- vitest@1.6.0spec.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. git@2.53.0), 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.4" }
development:
sandbox:
flox:
enabled: true
deps:
- deno@2.1.4
- kubectl@1.36.1
- terraform@1.9.5# Devcontainer: same deps, rendered as an apt-packages feature
spec:
language:
go: { module: github.com/example/agent, version: "1.26.4" }
development:
sandbox:
devcontainer:
enabled: true
deps:
- deno@2.1.4
- kubectl@1.36.1The ADL spec distinguishes two complementary concepts:
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: skill-creator@v1.0 # pin to a tag/branch/shalicense 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).
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: skill-creator@v1.0
# 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.
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.md
The 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.
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):
Runtime overrides for Fetch (resolution precedence: env > compile-time literal > default-disabled):
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).
Note: The code examples in this section are illustrative - they show the conceptual shape of the generated code but may not match the exact output of the current templates. For the authoritative generated output, refer to the Go templates in internal/templates/languages/go/ (config.go.tmpl, service.go.tmpl, tool.go.tmpl, main.go.tmpl).
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.
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]The configuration system generates type-safe structs with automatic environment variable mapping:
Generated Configuration (config/config.go):
Illustrative example - see internal/templates/languages/go/config.go.tmpl for the actual template. The Config struct is generated dynamically from spec.config entries; the Environment field shown below is not generated by the template.
type Config struct {
// A2A configuration (all A2A_ prefixed vars)
A2A serverConfig.Config `env:",prefix=A2A_"`
// Custom configuration sections (one per spec.config entry, excluding "tools")
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:
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: "noreply@example.com"
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 Tool Code:
Illustrative example - see internal/templates/languages/go/tool.go.tmpl for the actual template. Generated tools live under tools/, not skills/.
type ExportReportTool struct {
logger *zap.Logger
database database.DatabaseService
email *config.EmailConfig // Type-safe access to email config only
}
func NewExportReportTool(
logger *zap.Logger,
database database.DatabaseService,
email *config.EmailConfig,
) server.Tool {
tool := &ExportReportTool{
logger: logger,
database: database,
email: email,
}
return server.NewBasicTool(
"export_report",
"Export data and email report",
map[string]any{ /* schema */ },
tool.ExportReportHandler,
)
}
func (t *ExportReportTool) ExportReportHandler(ctx context.Context, args map[string]any) (string, error) {
// Direct access to email config subsection
apiKey := t.email.APIKey
fromAddress := t.email.FromAddress
provider := t.email.Provider
// ... implementation
}Main Registration:
Illustrative example - see internal/templates/languages/go/main.go.tmpl for the actual template.
// In main.go - config subsection is passed directly
exportReportTool := tools.NewExportReportTool(l, databaseSvc, &cfg.Email)
toolBox.AddTool(exportReportTool)Benefits of Config Subsection Injection:
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.servicesThe service injection system generates:
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 implementations
Each service generates a package with interface and factory:
Example internal/googleCalendar/googleCalendar.go:
Illustrative example - see internal/templates/languages/go/service.go.tmpl for the actual template.
type CalendarService interface {
// TODO: Define the methods for CalendarService service
// Example:
// SomeMethod(ctx context.Context, param string) error
}
type calendarServiceImpl struct {
// TODO: Add fields needed for this service
}
func NewCalendarService(logger *zap.Logger, cfg *config.Config) (CalendarService, error) {
// TODO: Implement constructor logic for CalendarService
logger.Info("initializing CalendarService service")
return &calendarServiceImpl{}, nil
}Skills automatically receive injected services as constructor parameters:
Example tools/create_event.go:
Illustrative example - see internal/templates/languages/go/tool.go.tmpl for the actual template. Generated tools live under tools/, not skills/.
type CreateEventTool struct {
logger *zap.Logger
calendar googleCalendar.CalendarService
cache cache.CacheRepository
}
func NewCreateEventTool(logger *zap.Logger, calendar googleCalendar.CalendarService, cache cache.CacheRepository) server.Tool {
tool := &CreateEventTool{
logger: logger,
calendar: calendar,
cache: cache,
}
return server.NewBasicTool(
"create_event",
"Create a new calendar event",
map[string]any{ /* schema */ },
tool.CreateEventHandler,
)
}The ADL CLI generates project scaffolding tailored to your chosen language:
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 (with --deployment kubernetes)
├── .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 instructions
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 (with --deployment kubernetes)
├── CLAUDE.md # AI assistant instructions (spec.development.ai.orchestrators.claudecode.enabled: true)
└── README.md # Documentation
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 # Documentation
All projects include these essential files regardless of language:
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:
The generated workflow automatically detects your Go version from the ADL file and configures the appropriate environment.
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:
The generated CD pipeline includes:
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:
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.0
The ADL CLI provides native support for deploying A2A agents to Google Cloud Run, offering a truly serverless deployment experience without Kubernetes complexity.
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: productionGoogle 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 imageWhen using --deployment cloudrun, the ADL CLI generates a deploy task in the Taskfile.yml that:
# 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 deployGenerate CloudRun deployment with continuous deployment:
adl generate --file agent.yaml --deployment cloudrun --cdThis creates:
Required GitHub Secrets:
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 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.
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: infocompatibilityDate defaults to a stable value when omitted, and compatibilityFlags defaults to nodejs_compat (the scaffold relies on Node.js API compatibility).
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_KEY# 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
# Validate and generate
adl validate examples/cloudflare-agent.yaml
adl generate --file examples/cloudflare-agent.yaml --output ./cloudflare-test
# Finish wiring the A2A handler in src/worker.ts, then
wrangler deployNote: Long-running/stateful work (the background task queue the Node entrypoint runs) needs Cloudflare Queues or Durable Objects. Those resource bindings were intentionally left out of the initial schema and may arrive in a later minor version.
The ADL CLI supports multiple development environments for isolated, reproducible development:
Configure Flox for your project by adding to your ADL file:
spec:
development:
sandbox:
flox:
enabled: trueGenerated files:
Configure DevContainer for your project:
spec:
development:
sandbox:
devcontainer:
enabled: trueGenerated files:
You can enable multiple sandbox environments simultaneously:
spec:
development:
sandbox:
flox:
enabled: true
devcontainer:
enabled: trueThis generates both Flox and DevContainer configurations, allowing developers to choose their preferred environment.
Enable server authentication in your ADL file:
spec:
server:
port: 8443
debug: false
auth:
enabled: trueThis generates enterprise-ready authentication scaffolding in your project.
Configure source control management for automatic CI/CD provider detection:
spec:
scm:
provider: github # gitlab support planned
url: "https://github.com/company/my-agent"
github_app: false # optional: enable GitHub App for CD
issue_templates: true # optional: generate GitHub issue templates
dependabot: true # optional: generate Dependabot configurationFeatures:
For enterprise environments, you can enable GitHub App-based CD deployment for enhanced security:
spec:
scm:
provider: github
url: "https://github.com/company/my-agent"
github_app: trueGitHub App CD Benefits:
Required GitHub Secrets:
The secret names are configurable via spec.scm.app_id_secret and spec.scm.app_private_key_secret if your organization uses different names.
When github_app: true is set, the generated CD pipeline will use GitHub App authentication instead of the default GITHUB_TOKEN, providing better security isolation for release management.
The ADL CLI supports multiple AI providers including OpenAI, Anthropic, Google AI, Groq, Mistral, DeepSeek, Cohere, Cloudflare, Moonshot, Ollama (for local LLMs), Ollama Cloud, and Nvidia. Each provider requires appropriate API keys to be configured as environment variables. See the ADL examples above for configuration details.
Enable artifacts support to allow your agent to create, store, and manage files and resources:
spec:
artifacts:
enabled: trueConfigure storage via environment variables (see generated README for A2AARTIFACT* variables). Supports both filesystem and MinIO/S3 storage backends.
Examples:
Enable OpenTelemetry instrumentation for the generated agent:
spec:
telemetry:
enabled: trueThe manifest field is a single on/off switch - exporter endpoints, ports, and sampling stay runtime concerns configured via environment variables in the generated .env.example:
Note: Telemetry generation currently supports Go and TypeScript only; Rust agents ignore spec.telemetry.
Examples:
Connect the generated agent to one or more MCP servers via the ADK's built-in MCP client:
spec:
agent:
provider: deepseek
model: deepseek-v4-flash
mcp:
enabled: true
servers:
- name: tools
transport: http
url: http://mcp-tools:8080enabled is the master switch. When true (and omitted the block is off), the generator wires an MCPClientManager into main.go that connects to the servers in the background, discovers their tools, and registers two selector tools - mcp_list_tools and mcp_call_tool - into the agent's toolbox. Everything else is a runtime concern: each mcp field maps 1:1 to an A2A_MCP_* variable in the generated .env.example (the manifest value is the default, overridden by the environment). A2A_MCP_SERVERS is derived from the http servers' base URLs. Defaults: endpoint=/mcp, refreshInterval=5m, dialTimeout=30s, callTimeout=30s, maxRetries=0, retryInterval=2s, retryMaxInterval=30s.
Note: The ADK MCP client is generated for Go agents only and is streamable-HTTP-only; stdio/sse servers are dropped from A2A_MCP_SERVERS (the validator warns), and the block is ignored for TypeScript/Rust agents.
Example:
The ADL CLI can automatically generate GitHub issue templates for your agent projects, providing standardized forms for bug reports, feature requests, and refactoring tasks:
spec:
scm:
provider: github
url: "https://github.com/company/my-agent"
issue_templates: true # Enable issue template generationWhen issue_templates: true is set, the following templates are generated in .github/ISSUE_TEMPLATE/:
Issue Template Features:
The ADL CLI can generate a .github/dependabot.yml manifest so generated agent projects keep their dependencies up to date automatically. The feature defaults to false and is opted into via spec.scm.dependabot:
spec:
scm:
provider: github
url: "https://github.com/company/my-agent"
dependabot: true # Enable Dependabot configurationWhen dependabot: true is set (and the SCM provider is GitHub), the generator emits a weekly-schedule manifest covering the ecosystems present in your ADL:
Each ecosystem groups all updates into a single PR per week to keep noise low. The default of false keeps the existing behavior unchanged for projects that manage dependency upgrades themselves.
The CLI includes example ADL files in the examples/ directory:
# Validate examples
adl validate examples/go-agent.yaml
adl validate examples/rust-agent.yaml
adl validate examples/typescript-agent.yaml
adl validate examples/cloudrun-agent.yaml
adl validate examples/cloudrun-ghcr-agent.yaml
# Generate from examples
adl generate --file examples/go-agent.yaml --output ./test-go-agent
adl generate --file examples/rust-agent.yaml --output ./test-rust-agent
adl generate --file examples/typescript-agent.yaml --output ./test-typescript-agent
adl generate --file examples/cloudrun-agent.yaml --output ./test-cloudrun-agent --deployment cloudrun
adl generate --file examples/cloudrun-ghcr-agent.yaml --output ./test-ghcr-agent --deployment cloudrun
# Generate with CI/CD pipeline
adl generate --file examples/go-agent.yaml --output ./enterprise-agent --ci --cd
adl generate --file examples/cloudrun-agent.yaml --output ./cloudrun-enterprise --deployment cloudrun --cdExample ADL Files:
See examples/README.md for the full catalog of all 18 example manifests.
The ADL CLI uses a sophisticated template system that generates language-specific projects:
The generator automatically detects your target language from the ADL file:
// Automatic detection based on spec.language configuration
func DetectLanguageFromADL(adl *schema.ADL) string {
if adl.Spec.Language.Go != nil { return "go" }
if adl.Spec.Language.Rust != nil { return "rust" }
if adl.Spec.Language.TypeScript != nil { return "typescript" }
return "go" // default
}Each language has its own file mapping that determines what gets generated:
Go Projects:
Rust Projects:
TypeScript Projects:
All templates receive a rich context object:
type Context struct {
ADL *schema.ADL // Complete ADL configuration
Metadata schema.GeneratedMetadata // Generation metadata (CLI version, timestamp, template, ADL file)
Language string // Detected language (go, rust, typescript)
GenerateCI bool // Whether to generate CI workflows
GenerateCD bool // Whether to generate CD workflows
EnableAI bool // Whether AI assistant features are enabled
AIToggles schema.AIAgentToggles // Per-agent AI toggles (Claude Code, Codex, Gemini, OpenCode, Infer)
GenerateCommand string // The CLI command used to generate the project
Skills []SkillView // Resolved skill metadata (frontmatter only)
BuiltinConfigs schema.ResolvedBuiltinConfigs // Decoded config for reserved built-in tools
Vendor vendor.View // Resolved user-declared extra dependencies
SandboxDeps sandbox.View // Resolved sandbox-level extra packages
}This allows templates to access any ADL configuration, toggle features based on SCM and AI settings, and generate language-appropriate code with the correct dependencies.
The ADL CLI automatically creates a .adl-ignore file during project generation to protect files containing TODO implementations. This file works similar to .gitignore and prevents important implementation files from being overwritten during subsequent generations.
When you generate a project, implementation files are automatically added to .adl-ignore to protect your business logic from being overwritten during regeneration.
You can control which additional files are generated or updated by editing the .adl-ignore file:
# .adl-ignore
# Skip Docker-related files if you have custom containerization
Dockerfile
docker-compose.yml
# Skip Kubernetes manifests if you use different deployment tools
k8s/
# Skip specific generated files you want to customize
middleware.go
auth.go
# Skip build configuration if you have custom setup
Taskfile.ymlgit clone https://github.com/inference-gateway/adl-cli.git
cd adl-cli
# Install dependencies
go mod download
# Build
task build
# Run tests
task test
# Format code
task fmt
# Lint
task lint# Run tests
task test
# Test with coverage
task test:coverage
# Test all examples
task examples:test
# Generate all examples
task examples:generateThe ADL CLI includes support for configurable acronyms to improve code generation readability. This feature helps generate more readable function and struct names by properly capitalizing acronyms in generated code.
Define custom acronyms in your ADL file's spec.acronyms field. These acronyms will be properly capitalized when generating identifiers in your code.
spec:
language:
go:
module: "github.com/company/my-agent"
version: "1.26.4"
acronyms: ["n8n", "xml", "mqtt", "iot", "uuid"]Without custom acronyms:
With custom acronyms:
The following acronyms are recognized by default:
Your custom acronyms extend these defaults and take precedence over them.
The ADL CLI supports custom post-generation hooks that run automatically after project generation. These hooks allow you to execute commands like formatting, linting, testing, or custom setup scripts.
Each language has sensible defaults:
Go Projects:
Rust Projects:
You can customize or extend the default behavior by adding a hooks section to your ADL file:
apiVersion: adl.inference-gateway.com/v1
kind: Agent
metadata:
name: my-agent
spec:
# ... other configuration ...
# Custom post-generation hooks
hooks:
post:
- "go fmt ./..."
- "go mod tidy"
- "go vet ./..."
- "go test -short ./..."
- "golangci-lint run --fix"Extended Go Development:
hooks:
post:
- "go mod download" # Download dependencies first
- "go generate ./..." # Generate code if needed
- "gofumpt -l -w ." # Improved formatting
- "golangci-lint run --fix" # Lint and auto-fix
- "go test -race -short ./..." # Run tests
- "go build -v ./..." # Verify build worksRust with Additional Tools:
hooks:
post:
- "cargo fmt"
- "cargo clippy --fix --allow-dirty"
- "cargo check --all-targets"
- "cargo test --lib"TypeScript/Node.js:
hooks:
post:
- "npm install"
- "npm run format"
- "npm run lint:fix"
- "npm run type-check"
- "npm test"The ADL CLI currently supports Go, Rust, and TypeScript, with plans to expand to additional programming languages:
We welcome community input on our roadmap! Please:
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
🤖 Powered by the Inference Gateway ecosystem
| Back | FazBrowse Home | New Git URL |