DEV Community

Luis Alcaraz
Luis Alcaraz

Posted on

Building agent tools out of other agent tools

Once an agent has a few good tools saved, the next one it builds usually needs pieces of the ones it already has. TAP now supports that directly. A primitive can declare other primitives as dependencies and call them from its own code.

I work on TAP at Telara. It's an MIT-licensed runtime that lets agents save repeated procedures as small programs with defined inputs and outputs, and developers write and maintain the same packages. This post walks through how composition works using an example from the repo.

The example

release-check has a parent and two children. api-release-brief collects public GitHub release and check-run data. task-summary-python reads a local task file and returns the open tasks.

The parent's manifest lists both children under uses. Each entry has an alias, a primitive reference, a version, an execution digest and an effect. Here is the call from the parent's Python entrypoint.

brief, tasks = tap.run_many([
    ("release_brief", {"owner": payload["owner"], "repo": payload["repo"], "ref": payload["ref"]}),
    ("open_tasks", {"status": "open"}),
])
Enter fullscreen mode Exit fullscreen mode

Both children run at once and the parent combines what comes back. If a child fails, the parent gets an error for that child and reports it as a failure.

You can read the manifest, the program and the setup notes. Setup saves the two children first and then runs the parent. Changing a child means saving a new version and updating its pin.

Who holds the access

The parent manifest has no GitHub origin and no task file path in it. The GitHub child declares its own network access and the task child declares its own file access. Each one runs with its own manifest, bindings, approvals and journal.

So the parent gets results and the children keep their permissions. The runner also rejects a parent whose declared effect is lower than one of its children. Missing pins, cycles and trees deeper than the limit get rejected too.

The tree shares one deadline and one max_dispatches budget. Approval prompts show the path from parent to child, so you know which piece is asking. If a run gets interrupted, resuming replays the children that finished and picks up the one that was in progress. A change whose outcome is unknown gets left for a person to check.

Partial results

Stacking tools means every layer has to pass along what it couldn't see. The GitHub child keeps unavailable evidence apart from the data it did return. On a successful check-run read it includes the API total, the returned count, the sampled count and truncation flags.

That lets the parent tell an empty list apart from a failed read. Concluding that a specific required check is missing takes more work. You'd need an expected-check list and full coverage of the places those checks live, and that part is yours to add. Network errors and malformed responses currently fail the whole run.

Reviewing a dependency change

tap manifest complete fills in the version, digest and effect from an installed primitive when you've only written the alias and reference. If the reference matches more than one package, it stops and lists the candidates.

tap diff shows children added, removed or re-pinned, plus changes to the interface, access and entrypoint. Treat a re-pin like any other dependency bump and run your own checks before you accept it.

The authoring guide covers the composition SDK for each supported language. There are examples for Bash, Python, JavaScript, TypeScript, Go, C++ and Rust. The compiled ones need the toolchain steps described in the guide.

Also new

The runner has a browser interface that maps navigate, read and act calls onto the browser your client provides. A package can keep its page checks and steps in one place and run against Claude in Chrome, the Codex browser or Playwright.

tap kit export writes a Docker Sandbox Kit config whose network allow list comes from the fetch origins your packages and their children declare. Signed packages can be checked against publisher keys you trust, and the signature is tied to the execution digest.

Try it

npm install -g @telaralabs/tap
tap setup
Enter fullscreen mode Exit fullscreen mode

Start with the composition example and read both child manifests before you grant fetch access. Composition runs in Claude Code and Codex CLI, and the README covers the other clients.

You can use TAP without a Telara account. I'm curious what you'd want a child tool to report back so its parent can handle a partial answer.

I work on TAP at Telara. This article was drafted with AI assistance.

Top comments (0)