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 (read-only).

Why this exists

Per-framework adapters are a treadmill. The JSON Schema contract is the long-term answer:

  • Pictograph maintains one source of truth (pictograph.agents.REGISTRY).
  • Your agent stack consumes JSON Schema natively — every modern framework supports it.
  • No bespoke adapter to maintain on either side.

The Python SDK still ships Claude + OpenAI adapters because their 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',
});

(Pictograph doesn’t ship a _dispatch endpoint in v1.0.0 — wire each tool to its underlying REST endpoint manually. The Toolkit.dispatch() Python method is the reference behavior.)

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 source 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()    # identical to the HTTP response payload

Or via the CLI:

pictograph agents export-tools -o tools.json

See also

Copied to clipboard