8000 feat(dev): add an agent jobs workspace and make workspace-agent by bjoaquinc · Pull Request #33 · dlt-hub/dlthub-init · GitHub
[go: up one dir, main page]

Skip to content

feat(dev): add an agent jobs workspace and make workspace-agent - #33

Open
bjoaquinc wants to merge 5 commits into
develfrom
agent-jobs-scaffold
Open

bjoaquinc wants to merge 5 commits into
develfrom
agent-jobs-scaffold

Conversation

@bjoaquinc
@bjoaquinc bjoaquinc commented Sep 16, 2026 •
Copy link
Copy Markdown
Contributor

Adds make workspace-agent, a dev-only workspace for the background agents
hackathon. Three commands from an empty checkout to a deployed agent workspace.

make workspace-agent
cd examples/agent-workspace
export AGENT__API_KEY=<key>
uv run dlthub local run loop_probe   # smoke test

Two tracks, one scaffold

file track
verified_agent.py runs the workbench's dlthub-platform:job-inspector, nothing to author
my_agent.py a working agent to edit: docstring is the prompt, parameters are the inputs, return type is the output

The failure material

jaffle_shop/ comes from dlt-hub/test-workspace (thanks @AstrakhantsevaAA) and
runs against the live Jaffle Shop API. One correct pipeline and four broken ones,
fired together with dlthub job trigger tag:jaffle:

pipeline outcome the bug
correct 935 / 10 / 6 rows the reference
bad_config fails base_url on /api/v2/, 404 on the first request
bad_incremental fails cursor_path on a field the API does not have
bad_pagination green, 100 of 935 rows paginator reads next from the body; this API uses the Link header
bad_selector green, 0 of 6 rows data_selector points at data.results; the API returns a bare array

Only the first two wake an agent. The two green ones are the interesting half:
a job.fail trigger cannot see them, so catching those means comparing row
counts against correct. That gap is what both tracks work on.

alerts.py is Track B's starting point. It fires on failure and records that
something broke; it cannot say why, because a trigger carries no logs or counts.

Cron schedules are stripped, so nothing fires unattended in a participant's
workspace. No credentials are needed for the pipelines themselves: the API is
public and the only token in the code is a deliberate REPLACE_ME placeholder.

Why it is dev-only

It pins two prereleases, dlt==1.30.1a0 (the agent launcher is not in any
stable release) and dlthub-client==0.28.5a1. Those must not ship in the
published wheel, so the template lives in dev/ rather than
src/dlthub_init/scaffolds/ and the make target overlays it after scaffolding.

The model endpoint is empty by default, so nothing org-specific lives in this
repo. Pass it at scaffold time:

make workspace-agent \
  AGENT_MODEL=azure:<deployment> \
  AGENT_API_URL=https://<resource>.cognitiveservices.azure.com/ \
  AGENT_API_VERSION=2024-12-01-preview

The toolkit workaround

scripts/place_toolkit_agents.py exists because dlthub ai toolkit install
never installs a toolkit's agents: dlt looks for them at <toolkit>/agents/
while the workbench ships them at <toolkit>/dlthub/agents/. Filed as
dlt-hub/dlt#4454. verified_agent.py uses the ordinary <toolkit>:<agent>
reference and needs no change once dlt is fixed: delete the script and its
Makefile line.

Verified

End to end against a local stack running dlt-hub/runtime#2109, with
dlt 1.30.1a0, dlthub-client 0.28.5a1, pydantic-ai 2.43.0, on Azure OpenAI:

  • All five pipelines behave as documented, including bad_pagination logging
    this run is green but incomplete — expected 935 customers, loaded 100.
  • job_inspector diagnosed bad_config as config / high confidence, citing
    both the run log and the line of source that causes it.
  • my_agent diagnosed bad_incremental the same way.
  • alerts fires only on failure.
  • Deploy accepts a background_agent manifest; AGENT__API_KEY as a workspace
    variable reaches the run; agent results and traces read back through
    /telemetry/v1/*.

Three Azure findings worth knowing: api_version is required even though
Azure's v1 GA API no longer needs it, the endpoint is the cognitiveservices
URL rather than a Foundry project URL, and AGENT__MODEL names the deployment.
Setting only AGENT__API_KEY leaves the model at the agent's default and sends
the key to Anthropic.

Not for merging yet

Agent jobs need dlt-hub/runtime#2109 merged and rolled out before platform tools
work on api.dlthub.dev; on the local stack with that branch they work today.
The hackathon clones this branch directly, so merging is not urgent.

`make workspace-agent` scaffolds a workspace for the background agents
hackathon: pinned to the dlt alpha that carries the agent launcher, pointed at
api.dlthub.dev, and set up in three commands. Two tracks share one scaffold, so
the fragile pin set lives in one place: verified_agent.py runs the workbench's
job-inspector, my_agent.py is a template to edit.

Dev-only and outside src/ on purpose. dlt is pinned to a branch archive, which
must never ship in the published wheel.

scripts/place_toolkit_agents.py works around `dlthub ai toolkit install`
skipping a toolkit's agents: dlt looks for them at <toolkit>/agents/ while the
workbench ships them at <toolkit>/dlthub/agents/, so the install reports success
and the agent silently never arrives.
Replaces the single broken_ingest job with dlt-hub/test-workspace's jaffle_shop
pipelines: one correct and four broken, covering four distinct failure classes.
Two fail outright and wake the agents; two run green while losing data, which no
job.fail trigger can see. That gap is the point, and it gives both tracks
something real to work on.

alerts.py becomes Track B's starting point: it already fires on failure and
records that something broke, but cannot say why.

Adds deltalake and s3fs, which the playground destination needs to write Delta
tables. Without them the pipelines extract fine and then fail at load.

Drops the cron schedules, keeping tag:jaffle, so nothing fires unattended in a
participant's workspace. Moves the mask helper and endpoint_report into
diagnostics.py.
The template skipped `run.Entity`, which the dlt branch treats as how an agent
job reaches the rest of the platform. Without it the manifest carries no
`expose.object_input`, so the web UI cannot offer the agent from a failed run's
row, and the run reports no entity so it never appears on that run's page. A
template people copy should not teach the omission.

Verified on a local stack: the manifest now carries object_input for both agents,
and my_agent's result reports job-run/<id> where it previously reported nothing.

Also passes loop inputs by keyword. `AgentLoop.run`'s first positional argument
is `instructions`, so a dict lands on a string path; the old `run({})` only
survived because an empty dict is falsy.
my_agent.py carried 15 comment lines explaining dlt's API semantics, which
buried the three things a participant is meant to edit. The descriptions now sit
in Doc() on every input and output field, where the model reads them too.

The README dropped from 193 lines to 72. It documented gotchas we hit while
building the scaffold and then fixed in it: the pins, the fastmcp extra, the
pydantic-ai floor, the toolkit workaround, and the agent declarations. A
participant gets the fixed version, so the working code is the reference. Also
drops a validation log that belonged in the pull request and was already stale.

Passes run_context into the loop inputs. A decorated function drives the loop
itself, so {{ run_context.* }} placeholders rendered blank; the launcher does
this for an agent declared by reference.
A fresh deploy had four working agents, which made the scaffold a demo rather
than a starting point. Per the hackathon flow: everyone declares the verified
job-inspector first, then writes their own.

verified_agent.py and my_agent.py are now stubs whose docstrings say what to
write; example_agent.py is the worked Python agent, kept as a reference and not
deployed. Both steps are the same motion: write a file, add it to
__deployment__.py, deploy. A fresh deploy has eight jobs and no agents.

Drops row_count_agent, which caught the two green pipelines. That is the most
interesting thing a team could build, so it should not ship. my_agent.py names
the gap and mentions that triggers also come in .success, without answering it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0