Getting started with agents
Background agents are in private preview.
Background agents are dltHub jobs that run an AI agent loop. They run unattended, for example after another job fails, and report a structured result next to the job run they acted on.
The agents ship with the AI Harness. The dlthub-platform toolkit includes job-inspector, a verified agent that diagnoses failed job runs.
Prerequisites
- uv and Python 3.12 to 3.14.
- A coding agent: Claude Code, Cursor, or Codex.
- The model name, endpoint URL, and API key for your agents.
Set up with your coding agent
Open your coding agent in your dltHub workspace, or in an empty directory to start from scratch, and paste this prompt:
Set up this directory for dltHub background agents. Use `uv run` and pass
`--non-interactive` to `dlthub` commands.
1. If there is no `.dlt/.workspace` file, run `uvx dlthub-init@latest`.
2. Add these dependencies to pyproject.toml and run `uv sync`:
"dlt[hub]==1.30.1a0", "dlthub[mcp]", "dlthub-client>=0.28.5",
"pydantic-ai-slim[anthropic,openai,google,mcp,spec]>=2.35.0", "aiohttp>=3.14.3"
3. Run `uv run dlthub ai toolkit install dlthub-platform --overwrite`, then
`uv run dlthub ai status`, and fix any warnings.
4. Declare the `job-inspector` agent in `__deployment__.py` with an explicit
trigger on the jobs I choose, never the default `job.fail:*`. Ask me which
jobs to watch, or which pipeline to build first if there are none.
I'll configure the model key and endpoint myself. Never ask for them, put them
in a command, or write them to a file.
Set the model credentials
Add the model and the endpoint URL to .dlt/config.toml. Every agent job in the workspace uses them:
[agent]
model = "azure:gpt-5.6-sol"
api_url = "<endpoint URL>"
api_version = "2024-12-01-preview" # Azure endpoints only
Set the API key yourself, in your own terminal, so your coding agent never sees it. Export it for local runs, and store it as a workspace secret for deployed runs, because the platform runner can't read your shell:
export AGENT__API_KEY=<your API key>
uv run dlthub login
uv run dlthub variable set AGENT__API_KEY --value "$AGENT__API_KEY" --secret --workspace
If your workspace is not connected to dltHub yet, run uv run dlthub workspace connect before variable set.
Deploy and run
job-inspector starts only when a job it watches fails. When the coding agent asks which jobs to watch, pick a job that can fail, for example one that calls an external API or reads credentials.
Deploy the workspace:
uv run dlthub deploy
Then run the watched job, from the CLI:
uv run dlthub run <job-name>
Or from the Web UI: open the Jobs page at app.dlthub.com, select the job, and start a run.
If the run fails, job-inspector starts on its own. To read its diagnosis, open the inspector run:
- From the failed run's page in the Web UI, which links to the inspector run.
- From the Agents tab, which lists all agents in your workspace and their runs.
Customize the job inspector
Override the inspector's defaults in __deployment__.py, for example its model, turn limit, or extra instructions:
job_inspector = run.agent(
"dlthub-platform:job-inspector",
trigger=[my_job.fail],
limits={"max_turns": 20},
instructions="focus on the loader step",
)
Build your own agent
Write your own agent as an AGENT.md file or as a Python function with the @run.agent decorator.
The examples below define workspace_report, an agent that reads the status of every job in the workspace and writes a report.
In an AGENT.md, the YAML frontmatter declares the tools, access, and output, and the Markdown body is the system prompt:
---
description: Reports the latest status of every job in the workspace. Read-only.
tools: [jobs]
access:
context: [read]
output:
type: object
properties:
jobs_total: { type: integer }
failed_jobs: { type: array, items: { type: string } }
---
List every job in the workspace and read the status of its latest run. Report
how many jobs there are and which ones failed. In `summary`, write a Markdown
table with one row per job: name, last run status, and when it ran.
Save it as agents/workspace_report/AGENT.md and declare it in __deployment__.py by its folder:
from dlt.hub import run
from dlt.hub.run import trigger
__all__ = [
# ...,
"workspace_report",
]
workspace_report = run.agent("agents/workspace_report", name="workspace_report")
In a Python function, the docstring is the system prompt, the parameters are the inputs, and the return type is the output schema:
from typing import List
from dlt.hub import run
from dlt.hub.run import trigger
class WorkspaceReport(run.TAgentOutput):
jobs_total: int
failed_jobs: List[str]
@run.agent(
tools=["jobs"],
access={"context": ["read"]},
)
async def workspace_report(run_context: run.TJobRunContext = None) -> WorkspaceReport:
"""List every job in the workspace and read the status of its latest run.
Report how many jobs there are and which ones failed. In `summary`, write a
Markdown table with one row per job: name, last run status, and when it ran.
"""
return await run_context["ai_loop"].run()