Describe-first AI agent – fluent-wp-client
A small Vercel AI SDK agent that is instructed to first call describeResourceTool whenever it meets an unfamiliar content type, then use the resulting schema to decide what to read or write. The pattern keeps the library thin: the model reasons about field meaning from the live schema instead of the AI SDK having to pre-digest it.
What the pattern looks like
Section titled “What the pattern looks like”-
Load the catalog once.
wp.explore()caches every content type, taxonomy, resource, and ability. SubsequentdescribeResourceToolcalls resolve from memory. -
Tell the model the rule. A system prompt instructs the agent to describe unfamiliar resources before touching them.
-
Expose three tools.
describeResourceToolfor introspection,getContentToolfor reads,saveContentToolfor writes. Create vs update is decided by whether the model includesid.
Example
Section titled “Example”import { generateText } from 'ai';import { openai } from '@ai-sdk/openai';import { WordPressClient } from 'fluent-wp-client';import { describeResourceTool, getContentTool, saveContentTool,} from 'fluent-wp-client/ai-sdk';
const wp = new WordPressClient({ baseUrl: 'https://blog.example.com', auth: { username: 'editor', password: process.env.WP_APP_PASSWORD!, },});
// Seed the catalog once. Every describe call below is served from memory.await wp.explore();
const tools = { describeResource: describeResourceTool(wp), readContent: getContentTool(wp), writeContent: saveContentTool(wp, { contentType: 'posts' }),};
const system = `You are an editorial assistant for a WordPress site.
Before reading or writing any content type for the first time, ALWAYS call"describeResource" with the matching kind and name (e.g. { kind: 'content',name: 'posts' }). Use its schema to decide which fields to request on readsand which fields to set on writes.
"writeContent" covers both creating and updating posts. Call it without "id"to create a new post, or with "id" to update an existing one. Only use itafter you have described "posts" in the current session.`.trim();
const { text } = await generateText({ model: openai('gpt-4o'), tools, maxSteps: 8, system, prompt: 'Draft a short announcement post introducing our new product launch, then publish it.',});Why this shape
Section titled “Why this shape”- One describe tool.
describeResourceToolcoverscontent,term,resource, andability. The system prompt does not need to enumerate per-kind introspection helpers. - Cached for free.
wp.explore()fills the client’s catalog cache. BecausedescribeResourceTooldelegates towp.content(name).describe()(and its sibling methods), repeat calls are synchronous in-memory lookups. - No library-side field digestion. Field descriptions, ACF choice labels, and plugin-added keywords travel through verbatim. The AI SDK schemas only constrain enum-like values (
contentType,taxonomyType,resourceType,fields) so bad calls are rejected locally before any HTTP round-trip.
Narrowing the introspection surface
Section titled “Narrowing the introspection surface”describeResourceTool accepts an include allowlist to restrict which kinds and names the model can describe. Any kind not listed in include disappears from the tool schema entirely.
const describe = describeResourceTool(wp, { include: { // Only expose two content types and one resource. content: ['posts', 'books'], resource: ['users'], // `term` and `ability` are omitted → removed from the tool's input schema. },});See the AI SDK guide for the full describe tool reference, including the error envelope returned on runtime validation failures.