DEV Community

Marouane TIJANI
Marouane TIJANI

Posted on AI-assisted

Give your AI agent a stock photo tool in 5 lines

Agents that write blog posts, landing pages or slides end up needing pictures. Generated images are not always the answer: you may want a real street in Lisbon, a real espresso machine, and a licence you can check.

Pexafy is a semantic search engine over millions of free-to-use photos from Unsplash, Pexels, Pixabay and other libraries. Your agent describes the photo it needs in plain language and gets back real photographs, each with its licence and the credit line to display.

Below: the same tool in LangChain, the Vercel AI SDK and any MCP-capable framework. Every snippet was run as printed.

What you need

export PEXAFY_API_KEY="pexafy_..."
export ANTHROPIC_API_KEY="sk-ant-..."
Enter fullscreen mode Exit fullscreen mode

LangChain and LangGraph (Python)

pip install -U langchain-pexafy langchain langchain-anthropic
Enter fullscreen mode Exit fullscreen mode
from langchain.agents import create_agent
from langchain_pexafy import PexafyToolkit

agent = create_agent("anthropic:claude-haiku-4-5", tools=PexafyToolkit().get_tools())

result = agent.invoke({"messages": [
    {"role": "user", "content": "Find a header photo for a post about remote work, with its credit line."}
]})
print(result["messages"][-1].content)
Enter fullscreen mode Exit fullscreen mode

The toolkit has three tools: search by description, find similar photos, get one photo. create_agent runs on LangGraph, and the tools also work with ToolNode or bind_tools(). The same package exists for LangChain.js: npm install langchain-pexafy.

Vercel AI SDK (TypeScript)

npm install pexafy-ai-sdk ai zod @ai-sdk/anthropic
Enter fullscreen mode Exit fullscreen mode
import { anthropic } from "@ai-sdk/anthropic";
import { generateText, stepCountIs } from "ai";
import { pexafyTools } from "pexafy-ai-sdk";

const { text } = await generateText({
  model: anthropic("claude-haiku-4-5"),
  tools: pexafyTools(),
  stopWhen: stepCountIs(5),
  prompt: "Find a header photo for a post about remote work, with its credit line.",
});
console.log(text);
Enter fullscreen mode Exit fullscreen mode

Any framework that speaks MCP

Pexafy also runs an MCP server: https://mcp.pexafy.com/mcp, with your API key as a Bearer header. Here it is in Pydantic AI:

pip install "pydantic-ai-slim[mcp,anthropic]"
Enter fullscreen mode Exit fullscreen mode
import os

from pydantic_ai import Agent
from pydantic_ai.mcp import MCPToolset, StreamableHttpTransport

pexafy = MCPToolset(
    StreamableHttpTransport(
        "https://mcp.pexafy.com/mcp",
        headers={"Authorization": f"Bearer {os.environ['PEXAFY_API_KEY']}"},
    )
).filtered(lambda ctx, tool: tool.name in {"search_photos", "search_photos_by_image"})

agent = Agent(
    "anthropic:claude-haiku-4-5",
    instructions="Find free stock photos and give each photo's credit line.",
    toolsets=[pexafy],
)

result = agent.run_sync("Find a header photo for a post about remote work.")
print(result.output)
Enter fullscreen mode Exit fullscreen mode

The filter keeps the two search tools; the others are for chat clients that show a photo grid. Tested setups for other frameworks: OpenAI Agents SDK, Claude Agent SDK, Google ADK, CrewAI, LlamaIndex, Mastra, Strands Agents.

What comes back

With the LangChain and AI SDK packages, each photo is one record (abridged):

{
  "rank": 1,
  "photo_id": "019e1ea7-2e82-7a34-a451-4c6c7c8250f4",
  "alt_text": "Red bicycle parked against white wall with front wheel facing left and back wheel right",
  "url": "https://images.unsplash.com/photo-1520538254843-27a40bae5e3a?w=1280",
  "width": 4896,
  "height": 3264,
  "orientation": "landscape",
  "photographer": "Mitchel Lensink",
  "source": "Unsplash",
  "license": "free",
  "credit": "Photo by Mitchel Lensink on Unsplash (https://pexafy.com/legal/licenses/#unsplash)"
}
Enter fullscreen mode Exit fullscreen mode

The agent can put url in your page, alt_text in the alt attribute and credit under the photo. On the free plan, show the credit line next to each photo you publish.

Links

Top comments (0)