Files
open-multi-agent/packages/core/examples/basics/structured-input.ts
T
Jack Chen bbdb928a5b docs(examples): make the example index runnable from a fresh checkout (#575)
The examples index is the first page most visitors open after the root
README, but it never said the scripts import the framework source and
need a repository checkout, which examples run without an API key, or
that four integrations existed at all.

- Add a "Run an example" block (clone, install, key, npx tsx) and note
  the two exceptions: observability-v2 needs a build, apps have their
  own start scripts. Explain how to port a script into a real project.
- Add a "No API key needed" table for the seven offline examples.
- Let the basics scripts switch provider through OMA_PROVIDER and
  OMA_MODEL instead of hard-coding Claude, following the convention the
  cookbook already uses.
- List external-agent-acp, external-agent-process, with-engram, and
  with-tencentdb-memory, and fail test:example-catalog when a catalog
  entry has no link in the index so it cannot drift again.
- Reorder sections so the 20-row providers table no longer sits between
  basics and the patterns and cookbook tables; mark production/ as empty.
- Align integrations/README.md with the apps grouping and define the
  mcp-<server>.ts versus with-<product>/ naming by example shape.
2026-09-04 22:51:45 +08:00

82 lines
2.5 KiB
TypeScript

/**
* Structured Multimodal Input
*
* Send an image and caller-owned message history through runAgent() without
* bypassing OMA's hooks, tracing, budgets, progress, or evaluation path.
*
* Run:
* npx tsx packages/core/examples/basics/structured-input.ts ./photo.png
*
* Prerequisites:
* ANTHROPIC_API_KEY env var must be set (default provider). To use any
* other built-in provider, set OMA_PROVIDER and OMA_MODEL plus that
* provider's key, for example:
* OMA_PROVIDER=deepseek OMA_MODEL=deepseek-chat DEEPSEEK_API_KEY=...
* OMA_PROVIDER=openai OMA_MODEL=gpt-5.4 OPENAI_API_KEY=...
* The model must accept image input. See docs/providers.md for the full
* provider and env var list.
* The image must be PNG, JPEG, GIF, or WebP.
*/
import { readFile } from 'node:fs/promises'
import { extname } from 'node:path'
import { OpenMultiAgent, type LLMMessage, type SupportedProvider } from '../../src/index.js'
// Defaults to Claude. Any built-in provider works: set OMA_PROVIDER and
// OMA_MODEL plus that provider's API key (see docs/providers.md).
const provider = (process.env.OMA_PROVIDER ?? 'anthropic') as SupportedProvider
const model = process.env.OMA_MODEL ?? 'claude-sonnet-4-6'
const imagePath = process.argv[2]
if (!imagePath) {
throw new Error('Pass an image path: npx tsx packages/core/examples/basics/structured-input.ts ./photo.png')
}
const mediaTypes: Readonly<Record<string, string>> = {
'.gif': 'image/gif',
'.jpeg': 'image/jpeg',
'.jpg': 'image/jpeg',
'.png': 'image/png',
'.webp': 'image/webp',
}
const mediaType = mediaTypes[extname(imagePath).toLowerCase()]
if (!mediaType) {
throw new Error('Unsupported image extension. Use PNG, JPEG, GIF, or WebP.')
}
const imageData = (await readFile(imagePath)).toString('base64')
const messages: LLMMessage[] = [
{
role: 'user',
content: [{ type: 'text', text: 'When I share an image, describe only visible facts.' }],
},
{
role: 'assistant',
content: [{ type: 'text', text: 'Understood.' }],
},
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image in three concise bullet points.' },
{
type: 'image',
source: {
type: 'base64',
media_type: mediaType,
data: imageData,
},
},
],
},
]
const oma = new OpenMultiAgent({
defaultProvider: provider,
defaultModel: model,
})
const result = await oma.runAgent({ name: 'vision-assistant' }, messages)
if (!result.success) throw new Error(result.output)
console.log(result.output)