AI Object Reference

Use useAIObject for generated or extracted content that decisions cannot express: titles, lists, nested fields, and prose inside a schema. For a yes/no, one category from a fixed set, or a position on an ordered rubric, use useAIDecisions. Decisions are far cheaper and faster, and the probability can drive the interface.

A feature can use both. Generate the content here, and judge priority, intent, or urgency with decide(). Do not put a boolean, a fixed category, or a rubric score in an object schema. generateObject does not stream partial objects, and it resolves to undefined instead of throwing when a request fails.

useAIObject

Returns

  • generateObject (function): Generate structured data.
  • isLoading (boolean): Whether a request is in progress.
  • error (Error | null): Current error.
  • clearError (() => void): Clear the current error.

generateObject Input

  • prompt (string, required): Description of the object to generate.
  • schema (object, required): JSON Schema for the output. Convert a Zod schema with z.toJSONSchema(...) before passing it. The hook does not accept a Zod object directly.
  • systemPrompt (string): Instruction that guides the AI.
  • enableWebSearch (boolean): Allow the AI to search for current information.
  • context (object): Additional JSON-serializable context.
  • attachments (FileList, File[], or an array of file or URL objects): Images, PDFs, audio, video, or YouTube URLs.
  • model (string): Model ID for the request.
  • reasoningEffort ("minimal", "low", "medium", or "high"): Reasoning depth for the request.

generateObject resolves to the generated object on success or undefined on failure. It never rejects.

Schema rules

Schemas must follow the structured-output subset:

  • The root type must be "object".
  • Every object must set "additionalProperties": false.
  • Every property must be listed in required; optional fields are not supported.
  • Supported types are "string", "number", "integer", "boolean", "object", and "array".
  • enum values must be strings. A quantity uses "number" with a description. A fixed category or ordered score is a decision, not an enum or number in this schema.
  • Keep schemas to type, properties, items, required, enum, default, description, and additionalProperties.

Example

import { useAIObject } from '@/hooks/use-ai'
import { usePersistentItem } from '@/hooks/use-persistent-item'

type Plan = {
  title: string
  summary: string
  tasks: string[]
}

export default function App() {
  const [plan, setPlan] = usePersistentItem<Plan | null>('plan', null)
  const { generateObject, isLoading, error } = useAIObject()

  const handleGeneratePlan = async (goal: string) => {
    const result = await generateObject<Plan>({
      prompt: `Generate a plan for: ${goal}`,
      schema: {
        type: 'object',
        properties: {
          title: { type: 'string' },
          summary: { type: 'string' },
          tasks: { type: 'array', items: { type: 'string' } },
        },
        required: ['title', 'summary', 'tasks'],
        additionalProperties: false,
      },
    })

    if (result) setPlan(result)
  }

  return (
    <div>
      {isLoading ? <p>Generating...</p> : null}
      {error ? <p className="text-destructive">{error.message}</p> : null}
      {plan ? <pre>{JSON.stringify(plan, null, 2)}</pre> : null}
    </div>
  )
}

Judge urgency or priority of that plan with useAIDecisions, not with another field in this schema.

generateObject accepts attachments in per-request options. Use files directly from local inputs, uploaded file URLs, or YouTube URLs:

const { generateObject } = useAIObject()

await generateObject({
  prompt: 'Extract the receipt details',
  schema: receiptSchema,
  attachments: [receiptImageFile],
})

await generateObject({
  prompt: 'Extract the main topics discussed',
  schema: topicsSchema,
  attachments: [{ url: youtubeUrl }],
})

Set enableWebSearch: true for prompts that need current information, such as weather, news, or live facts. Describe how each file or URL should map onto schema properties.

Reasoning Effort

Use reasoningEffort to trade latency for reasoning depth on generateObject:

  • "minimal": Fastest, with the least reasoning.
  • "low": Light reasoning.
  • "medium": Balanced reasoning.
  • "high": Maximum reasoning depth.

If omitted, the platform uses its default. Classification, yes/no judgments, and rubric scores belong on decisions, which do not use reasoning effort.

Model Selection

When no model is specified, the platform chooses an efficient default model for the user's plan. useAIObject uses text models. To expose model choice, pass a model ID and build selectors from listTextModels():

import { listTextModels, useAIObject } from '@/hooks/use-ai'

const models = listTextModels()
const [modelId, setModelId] = React.useState<string | undefined>(undefined)
const { generateObject } = useAIObject()

await generateObject({
  prompt: 'Generate a weeknight pasta recipe',
  schema: recipeSchema,
  model: modelId,
})

listTextModels() returns an array of model objects with:

  • id: Model ID to pass as model.
  • displayName: Human-readable display name.
  • provider: Provider name.
  • tier: "lite", "standard", or "advanced".
  • description: Short model description.
  • capabilities: Capability strings such as web_search, image_input, file_input, audio_input, and video_input.

Lite models are available on every plan. Standard models require Basic or Pro. Advanced models require Pro. More capable models cost more credits. Deprecated models automatically fall back to a recommended replacement.

Best Practices

  • Use generateObject's promise result and store it with usePersistentItem or React state.
  • Keep schemas small and explicit, and include additionalProperties: false on every object.
  • List every property in required. The schema does not support optional fields.
  • Include clear instructions when using attachments so the model knows how to use each file or URL.
  • Send a yes/no, a fixed category, or a rubric score through useAIDecisions.