AI agents are becoming the new integration layer.
They call APIs, read files, execute commands, talk to MCP servers, automate browsers, write code, query databases, send notifications, and sometimes even orchestrate other agents.
That sounds powerful.
It also sounds like a maintenance nightmare if every agent is defined differently.
Right now the agent ecosystem is moving very fast, but the developer experience is still fragmented. Every framework has its own way to describe tools. Every provider has its own interpretation of what “OpenAI compatible” means. Every runtime has its own bootstrap code. Every team ends up reinventing the same scaffolding again and again.
This is exactly the problem ADL tries to solve.
ADL stands for Agent Definition Language.
Think about it as OpenAPI, but for agents.
Instead of starting with code, you start with a manifest.
A simple YAML file that describes what the agent is, what it can do, which tools its internal runtime can call, which skills it knows and exposes, which provider it uses, which services it depends on, and how it should be generated or deployed.
From there, tooling can generate the boring parts.
And honestly, boring is good here.
Because the boring parts are usually the parts that break production.
Why agents need a contract
When we build HTTP APIs, we do not want every client to guess how the API behaves.
We use OpenAPI because it gives us a contract.
It describes the endpoints, request bodies, response bodies, authentication, validation rules, and everything else a client needs to interact with the service safely.
Agents need something similar.
Not because agents are the same as APIs, but because agents also need a contract.
A good agent definition should answer questions like:
- What is this agent called?
- What problem does it solve?
- Which model or provider does it use by default?
- Does it support streaming?
- Which tools can it call?
- What is the JSON schema for every tool input?
- Which services should be injected into tool implementations?
- Which skills should be loaded into the system prompt?
- How is the server configured?
- How should this be generated for Go, Rust, or TypeScript?
- How should this be deployed?
Without a contract, all of this becomes tribal knowledge.
It lives in README files, prompts, framework-specific code, environment variables, or worse, in someone's head.
That does not scale.
It also does not work well with GitOps.
Design-first agent development
I have always liked the design-first approach.
You define the interface first.
Then you generate, test, implement, and deploy around that interface.
This is why OpenAPI works well for APIs. The specification becomes the source of truth and the code becomes the implementation detail.
ADL follows the same idea, but applies it to agents.
The manifest becomes the source of truth.
For example, here is a trimmed view of browser-agent, an open source Playwright automation agent defined entirely through ADL:
apiVersion: adl.inference-gateway.com/v1
kind: Agent
metadata:
name: browser-agent
description: AI agent for browser automation and web testing using Playwright
version: 0.4.18
spec:
capabilities:
streaming: true
pushNotifications: false
stateTransitionHistory: false
config:
tools:
read:
enabled: true
max_lines: 2000
write:
enabled: true
edit:
enabled: true
browser:
headless: true
engine: chromium
session_timeout: 2m
viewport_width: 1920
viewport_height: 1080
# ...
tools:
- id: read
- id: write
- id: edit
- id: navigate_to_url
name: navigate_to_url
description: Navigate to a specific URL and wait for the page to fully load
tags:
- navigation
- browser
- playwright
schema:
type: object
properties:
url:
type: string
description: The URL to navigate to
wait_until:
type: string
description: When to consider navigation succeeded (domcontentloaded, load, networkidle)
default: load
timeout:
type: integer
description: Maximum navigation timeout in milliseconds
default: 30000
required:
- url
inject:
- logger
- playwright
# ... click_element, fill_form, extract_data, take_screenshot,
# execute_script, handle_authentication, wait_for_condition
skills:
- id: webapp-testing
bare: true
name: webapp-testing
description: 'Use this when the user asks to verify, validate, or test a webapp end-to-end. Performs reconnaissance-then-action: navigate, screenshot the rendered DOM, identify selectors, then exercise the flow.'
tags:
- testing
- qa
- e2e
# ... web-scraping, form-automation
agent:
provider: ''
model: ''
systemPrompt: |
You are an expert Playwright browser automation assistant.
Your core capabilities include navigation, element interaction,
data extraction, form automation, screenshot capture, JavaScript
execution, authentication handling, and synchronization.
# ...
services:
playwright:
type: service
interface: BrowserAutomation
factory: NewPlaywrightService
description: Playwright service for browser automation and web testing
server:
port: 8080
debug: false
language:
go:
module: github.com/inference-gateway/browser-agent
version: '1.26.2'
scm:
provider: github
url: https://github.com/inference-gateway/browser-agent
github_app: true
issue_templates: false
sandbox:
flox:
enabled: true
artifacts:
enabled: true
This is much easier to review than generated code.
You can open a pull request and immediately see what changed:
- a new tool was added
- a provider was changed
- streaming was enabled
- a skill was introduced
- a config section was added
- a Kubernetes deployment target was configured
That is exactly the kind of workflow I want for AI infrastructure.
Small declarative changes.
Versioned in Git.
Validated by schema.
Generated into real code.
Deployed like any other service.
Tools and skills are not the same thing
One important distinction in ADL is the difference between tools and skills.
Tools are deterministic function-call entrypoints.
A tool should be used when the agent needs to do something concrete:
- read a file
- execute a command
- query a database
- call an API
- send an email
- create a calendar event
Each tool has a schema. The schema defines what the model is allowed to pass into the tool. The generator can then create typed handlers, validation, and integration points in the target language.
Skills are different.
A skill is a reusable instruction set. Usually a markdown playbook that teaches the agent how to perform a workflow, follow a policy, or respond in a certain pattern.
For example:
- incident response
- Kubernetes troubleshooting
- release note generation
- code review guidelines
- support escalation workflow
- Terraform best practices
This distinction matters.
A tool gives the agent an action.
A skill gives the agent a way of thinking or working.
Mixing these two concepts together makes the system harder to reason about. ADL keeps them separate, while still allowing both to be part of the same agent definition.
Agents should be written in code, not only markdown
There is another reason I think agents should be generated into real code and not live only as markdown files.
Not every agent needs an LLM.
That sounds strange today because we often use the word agent as if it automatically means prompt plus model plus tools.
But that is not always true.
Some agents are mostly deterministic.
They receive an event, check a condition, call an API, transform some data, trigger a workflow, and return a result.
No reasoning required.
No token usage required.
No model call required.
And as of today, we already know that tokens are expensive.
So why should every agent pay the LLM tax if the workflow can be expressed as normal code?
Markdown is great for instructions, policies, and skills.
But execution belongs in code.
Code gives us types.
Code gives us tests.
Code gives us profiling.
Code gives us deterministic behavior.
Code gives us better control over cost.
This is where ADL becomes useful. The manifest can describe the agent contract, while the generated project gives developers a real place to implement the parts that should not depend on an LLM.
The model should be used where reasoning is actually useful.
Everything else should be boring, testable software.
Code generation should remove boilerplate, not control your project
The goal of ADL is not to hide everything behind magic.
The goal is to generate the repetitive parts so developers can focus on the business logic.
The ADL CLI can scaffold an enterprise-ready agent project from the manifest. Depending on the target language and options, this can include things like:
- server setup
- typed tool handlers
- JSON schema validation
- service injection
- structured configuration
- Docker files
- CI workflows
- Kubernetes manifests
- Cloud Run deployment files
- documentation
- AI assistant instructions
This is the part I personally care about a lot.
I do not want AI agents to be treated as small demos that only work locally.
I want agents to be normal software projects.
They should have tests.
They should have CI.
They should have a deployment story.
They should have predictable configuration.
They should be observable.
They should be reviewed like any other production service.
ADL is a step in that direction.
Built-in tools for common agent workflows
Some tools are so common that almost every coding or automation agent needs them.
For example:
readwriteeditbash
Instead of forcing every project to define these from scratch, ADL supports reserved tool IDs.
You can reference them in the manifest and let the generator create the implementation for the target language.
spec:
tools:
- id: read
- id: bash
- id: edit
The important part is that these tools are not blindly enabled.
They can be configured explicitly:
spec:
config:
tools:
read:
enabled: true
max_lines: 2000
bash:
enabled: true
whitelist:
- ls
- cat
- grep
- jq
timeout_seconds: 30
edit:
enabled: true
This is the right direction.
Powerful tools should be available, but they should also be controlled.
An agent that can execute shell commands needs boundaries.
An agent that can edit files needs boundaries.
The manifest makes those boundaries visible.
Service injection and configuration
A real agent usually needs more than just a prompt and a model.
It needs dependencies.
Maybe a database client.
Maybe a cache.
Maybe a Google Calendar client.
Maybe a Slack notifier.
Maybe an internal API client.
ADL allows services and configuration to be described in the manifest and injected into tool implementations.
This makes the generated code easier to test and easier to reason about.
Instead of a tool implementation reaching randomly into global state or parsing environment variables directly, it can receive the dependencies it needs.
That is boring software engineering.
Which is exactly the point.
AI agents do not remove the need for good engineering practices.
They make those practices more important.
A2A on the outside, OpenAI compatible on the inside
ADL agents speak A2A on the outside.
That is the external contract. Other agents, orchestrators, and registries discover and talk to an ADL agent through the A2A protocol.
A2A is intentionally minimal. It only defines two message roles: user and agent. There is no system role, no assistant role, and no tool role.
That is not an oversight.
A2A is designed so that an A2A server does not have to contain an LLM at all. It could be a deterministic worker, a workflow engine, or a thin wrapper around a normal HTTP service. Tying the protocol to LLM-specific concepts like a tool role would have leaked an implementation detail into the contract.
For the agents that do want an LLM, ADL plugs into the Agent Development Kit from the Inference Gateway ecosystem. The ADK can wire in an OpenAI-compatible agent runtime, which is what lets the same generated project run against OpenAI, Anthropic, DeepSeek, Groq, Ollama, or any provider that exposes the same shape, usually through the Inference Gateway.
This is where translation enters the picture.
In the OpenAI API, a conversation is a list of messages with roles like system, user, assistant, and tool. The tool role is how the model is told what a tool call returned. Without it, function calling round-trips do not work.
A2A does not need those roles, but the OpenAI runtime sitting behind it does.
So the generated code translates. Tool calls and tool results get folded into structured parts of agent messages on the way out, and expanded back into proper OpenAI system, assistant, and tool messages before being sent to the model.
The protocol stays LLM-agnostic.
The runtime stays LLM-friendly.
And the user does not have to write that translation layer themselves.
Why this matters for GitOps
If you are building agents for production, Git should be the control plane.
Not a dashboard.
Not a prompt hidden somewhere in a SaaS product.
Not a manually configured workflow that only one person understands.
With ADL, the agent definition can live in Git.
A change to the agent becomes a normal pull request.
You can review it.
You can validate it.
You can generate code from it.
You can deploy it through CI/CD.
You can roll it back.
You can compare versions.
You can answer the most important production question:
What changed?
This is also why ADL fits naturally into the Inference Gateway ecosystem.
Inference Gateway provides the unified access layer for LLM providers.
The ADK helps build A2A-compatible agents.
The registry helps distribute reusable agents and skills.
The CLI helps developers run and orchestrate real workflows.
ADL gives all of this a declarative language.
Vendor-neutral by design
One of the biggest risks in the current AI ecosystem is vendor lock-in.
Not just at the model level.
At the framework level.
At the tool definition level.
At the agent runtime level.
At the deployment level.
ADL should not care if the default provider is OpenAI, Anthropic, DeepSeek, Ollama, Google, Mistral, Groq, or something else.
The model should be replaceable.
The provider should be replaceable.
The generated runtime should be understandable.
The manifest should remain the contract.
That is the main reason I think this direction is important.
The future of agents should not be locked behind one vendor, one framework, or one hosted platform.
Agents should be portable artifacts
The next step for agents is distribution.
It is not enough to generate code.
Developers need a way to package, version, publish, discover, and deploy agents and skills.
This is where open standards matter.
If an agent can be described declaratively, generated consistently, and packaged using infrastructure-friendly patterns, then it becomes much easier to distribute.
This is the same reason containers won.
Not because containers were cute.
Because they gave us a portable artifact.
Agents need the same kind of thinking.
A manifest.
A generated runtime.
A versioned artifact.
A registry.
A deployment story.
A rollback story.
Without that, agents stay as demos.
With that, agents become infrastructure.
What I want ADL to become
My goal with ADL is simple.
I want developers to define an agent in YAML and get a production-ready server.
Not a toy.
Not a notebook.
Not another framework that only works in a perfect demo.
A real project that can be built, tested, deployed, reviewed, and improved over time.
The developer should still own the code.
The generated project should still be understandable.
The manifest should still be simple enough to review.
And the ecosystem should stay open enough that other tools can consume the same definition.
That is the real value.
Not code generation by itself.
A shared contract.
Closing thoughts
We are still early.
There will be breaking changes.
There will be better ideas.
There will be parts that need to be redesigned.
That is fine.
The important thing is to move toward a more open, declarative, and production-friendly way of building agents.
Agents are becoming infrastructure.
Infrastructure needs contracts.
ADL is my attempt to give agents that contract.
If you worked with OpenAPI before, the idea should feel familiar.
Define first.
Generate second.
Implement what matters.
Deploy like real software.
Use the model where reasoning adds value.
Use code where deterministic behavior is enough.
That is the direction I want to push with ADL.
Repository: https://github.com/inference-gateway/adl
ADL CLI: https://github.com/inference-gateway/adl-cli
Inference Gateway: https://github.com/inference-gateway/inference-gateway
