Skip to main content

Overview

Tool nodes let you integrate external services and custom Python code directly into your workflow — without needing to write an LLM prompt. Any node with type: tool is a tool node.
Two adapters are currently supported:

Common fields

All tool nodes share these top-level fields.

output_key and context storage

Tool output is stored under the node ID and its output_key. For example, a node named fetch_diff with output_key: diff exposes its result as {{ fetch_diff.diff }}. Downstream agent nodes reference this value in their system prompts using Jinja-style template syntax:
If output_key is omitted it defaults to output, so the reference becomes {{ <node_id>.output }}.
Reference upstream nodes by their ID ({{ fetch_diff.diff }}), not via the working namespace. The load-time linter rejects {{ working.<node_id>.* }}. Reserve working.* for custom paths you write to or seed in state.

HTTP adapter

Use tool: http to call an HTTP endpoint.

HTTP config fields

Response handling

  • If the response Content-Type is application/json, the body is parsed and the result is a Python dict or list.
  • Otherwise, the raw response text string is stored.

Error behaviour

Any non-2xx status code raises a ToolError with the HTTP status code and response body excerpt in the message. Network errors (DNS failures, connection refused) and timeouts also raise ToolError.

Python adapter

Use tool: python to call any importable Python function.

Python config fields

Module resolution

The module is resolved using importlib.import_module against the user’s runtime environment (sys.path), not against the sirenspec package. This means any module that is importable in the process where sirenspec runs can be used — your own application code, installed packages, or local scripts. Synchronous functions are run in a thread-pool executor so they do not block the event loop. Async functions are awaited directly.

Error behaviour

  • ModuleNotFoundErrorToolError with message "Cannot import module '...'"
  • Missing attribute → ToolError with message "Module '...' has no attribute '...'"
  • Exception during call → ToolError with the original exception type and message included

Retry and failure handling

  • retry: N — the tool is attempted N + 1 times total before giving up.
  • on_failure: raise (default) — propagates a ToolError and marks the workflow as "failed".
  • on_failure: skip — stores null under the output key and lets the workflow continue.

Full example: PR summarizer

This workflow fetches a GitHub pull-request diff over HTTP and then asks an LLM to summarise it.
Run it with:
A working copy of this example is available in the PR Summarizer cookbook recipe.

ToolError

All tool failures raise sirenspec.exceptions.ToolError (a subclass of SirenSpecError). The exception message always includes the adapter name and the upstream error:
ToolError exposes three attributes:

JSON Schema

The sirenspec.schema.json artifact validates tool nodes inline with agent nodes. IDEs that support JSON Schema (VS Code, JetBrains) will autocomplete type: tool, tool:, and all config fields automatically.