Sign in Get started

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.

View as Markdown

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:

  1. Fetch /api/v1/developer/tools.json once at startup.
  2. Hand the tools array to your LLM as the function/tool spec.
  3. When the LLM emits a tool call, look up the tool by name.
  4. Map name → REST endpoint (see the SDK resources for canonical mappings).
  5. 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

Copied to clipboard