Dynamic discovery
Use `GET /api/v1/developer/tools.json` to wire Pictograph into any agent framework that speaks JSON Schema - no Pictograph-specific adapter required.
The Pictograph SDK ships first-party adapters for Claude and OpenAI. For everything else (Vercel AI SDK, LangChain, raw HTTP clients, custom dispatchers), the registry is exposed as JSON Schema at:
GET https://api.pictograph.io/api/v1/developer/tools.json
Authenticated with the same X-API-Key header; any role works, since the read is
read-only.
Source: agents/_registry.py
Per-framework adapters are a treadmill. One source of truth
(pictograph.agents.REGISTRY), published as JSON Schema, means no bespoke adapter on
either side. The Python SDK still ships Claude and OpenAI adapters because those two
ecosystems are big enough to warrant the convenience; everyone else gets the
open-standard path.
Vercel AI SDK
import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
const headers = { 'X-API-Key': process.env.PICTOGRAPH_API_KEY! };
const { tools } = await fetch(
'https://api.pictograph.io/api/v1/developer/tools.json',
{ headers },
).then(r => r.json());
// Build a tools map keyed by name. The execute() function dispatches
// back to the Pictograph REST API directly - no Python required.
const pictographTools = Object.fromEntries(
tools.map((t: any) => [
t.name,
tool({
description: t.description,
parameters: t.input_schema, // Vercel accepts JSON Schema directly
execute: async (args: any) => {
// Map tool name → REST endpoint.
// (See: jsonschema-to-rest mapper, or hardcode the routes you use.)
const res = await fetch(
`https://api.pictograph.io/api/v1/developer/_dispatch/${t.name}`,
{ method: 'POST', headers, body: JSON.stringify(args) },
);
return res.json();
},
}),
]),
);
const result = await generateText({
model: anthropic('claude-opus-4'),
tools: pictographTools,
prompt: 'List my Pictograph datasets',
});
(There is no generic _dispatch REST endpoint - wire each tool to its own REST
endpoint. Toolkit.dispatch() in Python is the reference behaviour.)
LangChain
from langchain_core.tools import tool
import requests, os
headers = {"X-API-Key": os.environ["PICTOGRAPH_API_KEY"]}
schema = requests.get(
"https://api.pictograph.io/api/v1/developer/tools.json",
headers=headers,
).json()
# Build LangChain tools from the JSON Schema:
def make_tool(spec):
@tool(spec["name"], description=spec["description"], args_schema=...)
def _run(**kwargs):
# Call the matching REST endpoint with kwargs.
...
return _run
langchain_tools = [make_tool(t) for t in schema["tools"]]
For LangChain specifically, you can also use the Pictograph Python SDK
directly inside a @tool - that’s often simpler than rebuilding the
dispatch loop:
from langchain_core.tools import tool
from pictograph import Client
client = Client()
@tool("list_datasets", description="List Pictograph datasets in your org.")
def list_datasets(limit: int = 100) -> list[dict]:
return [d.model_dump(mode="json") for d in client.datasets.list(limit=limit)]
This trades the dynamic-discovery benefit for typed, tested SDK calls - worth it for production.
Custom dispatchers
If you’re rolling your own:
- Fetch
/api/v1/developer/tools.jsononce at startup. - Hand the
toolsarray to your LLM as the function/tool spec. - When the LLM emits a tool call, look up the tool by name.
- Map name → REST endpoint (see the SDK resources for canonical mappings).
- Send the args as the JSON body, return the response to the LLM.
Or use the Python SDK as a server-side dispatcher and only expose tool names + schemas to your client - usually the cleanest production architecture.
Snapshot file
The same registry ships in the Python SDK package - useful for offline work or if you want to bundle the schema with your agent:
from pictograph.agents import Toolkit
from unittest.mock import MagicMock
toolkit = Toolkit(MagicMock())
schema = toolkit.as_json_schema() # the bare list - the endpoint's "tools" value
Or via the CLI:
pictograph agents export-tools -o tools.json
See also
- Agents - overview - the three integration paths.
- Tool registry endpoint - full spec.
- Cookbook - concrete recipe examples.