Image Generate logo

Image Generate

OrganizationPopular
Prismer-AI
image-generate

Generate an image from a text prompt via the cloud LLM image proxy, persist it as a content-addressed workspace asset, and return a ContentBlock that downstream renderers can attach. Use whenever the user asks "draw / generate / make an image of …", an agent needs a diagram / illustration as a follow-up artifact, or a task description explicitly demands visual output. Do NOT use for editing or describing existing images — `assets` covers reads, and image editing is a separate skill.

Overview

PublisherPrismer-AI
RepositoryPrismerCloud
Skill nameimage-generate
Stars
1.6K
Forks
14
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by Prismer-AI on GitHub. Read the source before you install it.

Installation

Install the Image Generate AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/Prismer-AI/PrismerCloud.git /tmp/PrismerCloud
mkdir -p .claude/skills
cp -r /tmp/PrismerCloud/sdk/prismer-cloud/built-in-skills/image-generate .claude/skills/image-generate
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Image Generate in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Image Generate on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Image Generate is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Image Generate

Turn a text prompt into a content-addressed image asset plus a v2.0 §4.6 ContentBlock that the chat renderer can surface inline. The skill is a thin orchestration over two existing surfaces:

  1. LLM image gateway — the cloud's NewAPI proxy at POST /api/v1/images/generations (OpenAI-compatible — see §"Hand-off" if the endpoint is not yet wired in your deployment).
  2. Asset storePOST /api/im/assets (multipart) on the cloud, returning a stable assetId + contentHash. Generated bytes flow through the content-addressed pipeline like any other asset — same de-dup, same audit trail, same URI scheme (prismer://assets/<assetId>).

The skill's only output contract is a ContentBlock referencing the asset. Raw bytes / data: URIs / pre-signed URLs MUST NOT be embedded in prose; doing so defeats caching and makes follow-up retrieval impossible (same rule as the assets skill).

When to use

  • The user says "draw", "generate an image of …", "make me a picture / poster / diagram / illustration".
  • A task description includes a produce_image: field or a kind: image artifact expectation.
  • You need to fabricate a visual that does not exist in any source — if the visual already exists, use assets to read it, not this skill.
  • A downstream skill (canvas-design, slack-gif-creator, web-artifacts-builder) requires a generated source image as input.

Not when to use

  • Editing / variation / inpainting an existing image — that's a separate upcoming skill (image-edit). Don't fake it by reading + regenerating.
  • Describing what's in an image — use a vision-capable adapter, no generation needed.
  • Pure ASCII / SVG / Mermaid graphics that the LLM can emit as text — those belong in the chat body, not in an asset.
  • Privacy-sensitive renderings (faces, identifiable individuals) without explicit user confirmation. The skill does not gate this; the agent must.

API Reference

There is no cloud image generate subcommand in the runtime CLI today (release 201 audit, sdk/prismer-cloud/runtime/src/cli/commands/). Call the cloud HTTP endpoint directly from a small Python / Node script in the skill runtime, then hand the bytes to cloud asset upload for the content-addressed write. Adding a dedicated CLI verb is tracked as a future release; until then, do not invent the command — it will exit with "unknown command".

HTTP shape:

http
POST /api/v1/images/generations
Authorization: Bearer <user JWT or sk-prismer-* key>
Content-Type: application/json

{
  "prompt":  "<text prompt, 1..4000 chars>",
  "model":   "gpt-image-1",                 // or "dall-e-3", deployment-dependent
  "size":    "1024x1024",                   // 256x256 | 512x512 | 1024x1024 | 1792x1024 | 1024x1792
  "n":       1,                             // skill always uses 1 (return single ContentBlock)
  "response_format": "b64_json"             // skill requires bytes — never "url"
}

Successful response (OpenAI shape):
{
  "created": 1716345600,
  "data": [{ "b64_json": "<base64 PNG bytes>" }]
}

After receiving bytes the skill MUST upload to the cloud asset store (POST /api/im/assets, multipart) and use the returned assetId in the ContentBlock. Bytes never leak into chat.

Workflow

  1. Validate inputs. Prompt 1..4000 chars; size in the allow-list above; workspaceId resolved (defaulting to the active workspace if none supplied).

  2. Generate. POST to /api/v1/images/generations with response_format: 'b64_json'. Capture b64_json (single image).

  3. Decode + hash. Base64-decode to bytes, compute SHA-256 client-side, and compare against the upload response's contentHash field (server validates too — use x-content-sha256 header).

  4. Upload as asset. Multipart POST to /api/im/assets:

    • file — Blob with image/png MIME and filename generated-${shortHash}.png
    • workspaceId, kind=image, description=<prompt[0..500]>
    • sourceTaskId / sourceAgentImUserId (if available from runtime context)
    • folderPath=/generated/images/${YYYY-MM} (auto-organized, optional)
  5. Emit ContentBlock. Return — and only return — a ContentBlock pointing at the new asset. Shape exactly as v2.0 §4.6 (Anthropic-shape, not OpenAI):

    json
    {
      "kind":      "image",
      "assetId":   "<returned assetId>",
      "mediaType": "image/png",
      "alt":       "<prompt truncated to 100 chars>"
    }

Operating Rules

  • Always response_format: b64_json. Never url — the OpenAI URL is short-lived, doesn't survive the content-address round-trip, and tempts you to leak it into chat (which defeats the asset model).
  • One image per call. n=1 only. If the user wants variants, call the skill multiple times — each variant gets its own assetId so the user can pick + delete cleanly.
  • Hash check is non-negotiable. Server enforces x-content-sha256; if the hashes disagree, abort and surface the mismatch — the bytes were corrupted in flight.
  • Never inline base64 / data:<mime>;base64,... in the reply body. The whole point of the skill is to avoid that anti-pattern. If you find yourself about to do so, stop and check that the asset upload actually succeeded.
  • Default size = 1024x1024 unless the user explicitly asks for portrait (1024x1792) or landscape (1792x1024). 256/512 only when budget is tight.
  • Cost-aware: image gen is far more expensive than a chat completion. Tell the user the model + size you picked before spending more than 1 credit's worth, and surface the actual cost from the response.

ContentBlock output (v2.0 §4.6 / Gap E-⑤)

This skill produces a single image ContentBlock per successful generation. It MUST NOT also dump the base64 / pre-signed URL into the reply — that violates the §4.6 rule (asset-by-reference, not asset-by-value) and breaks the chat renderer's preview pipeline.

json
{ "kind": "image", "assetId": "<assetId>", "mediaType": "image/png", "alt": "<prompt summary, ≤100 chars>" }

The reply envelope from this skill (when invoked via the agent runtime) looks like:

json
{
  "ok": true,
  "result": {
    "assetId":     "<assetId>",
    "contentHash": "<sha256 hex>",
    "sizeBytes":   123456,
    "cdnUrl":      "<optional, server may include>",
    "model":       "gpt-image-1",
    "size":        "1024x1024",
    "promptHash":  "<sha256 of prompt for de-dup>"
  },
  "contentBlocks": [
    { "kind": "image", "assetId": "<assetId>", "mediaType": "image/png", "alt": "<prompt[0..100]>" }
  ]
}

Legacy callers that only know how to parse result.assetId keep working (field preserved). Multimodal-aware callers prefer contentBlocks[] — adapters and the chat renderer both check contentBlocks first per the §4.6 prefer-blocks rule.

Failure modes

StatusWhereCauseWhat to surface
400LLM proxyprompt too long / disallowed contentPrompt rejected; surface the proxy's error message verbatim. Do NOT retry the same prompt.
402LLM proxynot enough creditsTell the user the cost + ask them to top up. Don't burn credits on retries.
415asset uploadserver rejected MIME (not in allow-list)Should not happen — image/png is allow-listed. If it does, this is a deployment bug; flag it.
422asset uploadx-content-sha256 mismatchBytes corrupted in flight. Retry once; if it persists, fail the skill and tell the user.
5xxeitherupstream outageRetry with exponential backoff up to 2 times, then fail loudly. Do NOT fabricate the assetId.

Output reporting

After successful generation:

[image-generate] generated assetId=<id> model=<model> size=<WxH> sha=<short>
                 cost=<credits>c prompt="<first 60 chars>…"

Then in chat, return ONLY the ContentBlock (the renderer surfaces the image preview). One-line caption may accompany it if useful ("Here's the illustration you asked for.").

After failure: report status + proxy error code + message verbatim. Do not silently retry on 4xx (those are the user's prompt / quota — they need to know).

Backing capabilities (Gap E-⑤ mapping)

  • LLM image gateway: POST /api/v1/images/generations (NewAPI proxy wired in Wave 6 G1 at src/app/api/images/generations/route.ts; gateway reuses proxyToNewAPI in src/lib/llm-proxy.ts with image-specific billing via calculateImageCredits). Setting env MOCK_LLM_IMAGES=true bypasses NewAPI and returns a fixture 1×1 PNG (for integration tests that should not burn real image-gen credits).
  • Asset store: POST /api/im/assets (multipart) — src/im/api/assets.ts line 2729+. Returns IMAsset with id, contentHash, cdnUrl, sizeBytes.
  • ContentBlock contract: v2.0 §4.6 — sdk/prismer-cloud/typescript/src/types.ts lines 278–296 (8-variant discriminated union, Anthropic-shape).
  • Reply attachment plumbing: AgentDispatchReplyPayload.attachments — same path as the assets skill's image-resolve output. Chat renderer surfaces previews from attachments / contentBlocks automatically.

Examples

Example 1 — User asks for an illustration

User: "Draw an isometric server room with glowing blue racks"

Skill flow:
  POST /api/v1/images/generations
    { prompt: "An isometric...", model: "gpt-image-1",
      size: "1024x1024", n: 1, response_format: "b64_json" }
    ← 200 { data: [{ b64_json: "<bytes>" }] }

  decode + sha256 → "8f4a..."

  POST /api/im/assets (multipart)
    file=generated-8f4a.png  kind=image  workspaceId=...
    x-content-sha256: 8f4a...
    ← 200 { data: { id: "asset_<...>", contentHash: "8f4a...",
                    cdnUrl: "/api/im/assets/asset_<...>" } }

Reply envelope:
  { ok: true,
    result: { assetId: "asset_<...>", contentHash: "8f4a...", ... },
    contentBlocks: [
      { kind: "image", assetId: "asset_<...>", mediaType: "image/png",
        alt: "An isometric server room with glowing blue racks" }
    ] }

Example 2 — Task-pinned generation for kanban artifact

Task input: { produce_image: { prompt: "Logo: minimalist owl, monochrome",
                                size: "1024x1024" } }

Skill call: POST /api/v1/images/generations with the prompt, then
`cloud asset upload generated.png --task-id "$PRISMER_TASK_ID"` so the
kanban task review board surfaces the image inline (chat renderer reads
contentBlocks from the asset attachment).

Example 3 — Failure: prompt rejected

User: "<disallowed content>"
LLM proxy: 400 { error: { code: "content_policy_violation", ... } }

Skill response:
  { ok: false,
    error: { code: "content_policy_violation",
             message: "<proxy's verbatim message>" } }

Do NOT retry. Do NOT fabricate an assetId.

Anti-patterns

  • ❌ Returning the raw base64 in result.image_b64 for chat to render. The chat renderer expects ContentBlock referencing an asset; raw bytes bypass caching.
  • ❌ Using response_format: 'url' and pasting the OpenAI URL into the reply. URL expires; user clicks later → 404.
  • ❌ Skipping the asset upload "to save time" when the generated image is tiny. Tiny images still need stable IDs for follow-up retrieval and audit trail.
  • ❌ Calling the skill in a loop to "generate variants" — call once per variant with explicit prompt deltas. The de-dup hash will catch identical prompts.
  • ❌ Setting n > 1. The ContentBlock output shape is single-image; multi would force you to fabricate which one to attach.

Hand-off — endpoint provisioning

Cloud-side endpoint wired in Wave 6 G1. POST /api/v1/images/generations is now provisioned at src/app/api/images/generations/route.ts and uses the same proxyToNewAPI helper that backs /api/chat/completions + /api/embeddings. Image-specific billing lives in src/lib/llm-pricing.ts::calculateImageCredits (per-image USD pricing, no token semantics). Setting MOCK_LLM_IMAGES=true returns a fixture PNG without hitting NewAPI — used by F6 integration tests.

Historical handler template (matches the landed implementation):

ts
// src/app/api/images/generations/route.ts (NEW)
import { NextRequest, NextResponse } from 'next/server';
import { apiGuard } from '@/lib/api-guard';
import { checkRateLimit, rateLimitResponse } from '@/lib/rate-limit';
import { FEATURE_FLAGS } from '@/lib/feature-flags';
import { proxyToNewAPI } from '@/lib/llm-proxy';
import { ensureNacosConfig } from '@/lib/nacos-config';

export async function POST(request: NextRequest) {
  await ensureNacosConfig();
  if (!FEATURE_FLAGS.LLM_PROXY_ENABLED) {
    return NextResponse.json(
      { error: { message: 'LLM proxy is not enabled' } }, { status: 503 });
  }
  const guard = await apiGuard(request, { tier: 'tracked' });
  if (!guard.ok) return guard.response;
  const rl = checkRateLimit(guard.auth.userId, 'llm');
  if (!rl.allowed) return rateLimitResponse(rl);
  return proxyToNewAPI(request, guard, '/v1/images/generations');
}

Until this lands, the skill operates in mock mode — see scripts/test-image-generate-skill.ts which proves the generate→upload→ContentBlock chain by stubbing the LLM bytes (a 1x1 PNG) and hitting the real /api/im/assets upload, so the asset half of the contract is fully validated against production code paths.

Frequently asked questions

What does the Image Generate AI skill do?

Generate an image from a text prompt via the cloud LLM image proxy, persist it as a content-addressed workspace asset, and return a ContentBlock that downstream renderers can attach. Use whenever the user asks "draw / generate / make an image of …", an agent needs a diagram / illustration as a follow-up artifact, or a task description explicitly demands visual output. Do NOT use for editing or describing existing images — `assets` covers reads, and image editing is a separate skill.

Why use Image Generate on TypingMind?

Because you install it once and use it with any model. Image Generate is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Image Generate in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/Prismer-AI/PrismerCloud/tree/main/sdk/prismer-cloud/built-in-skills/image-generate. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Image Generate?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Image Generate?

As many as you like. As long as a model supports skills, you can use Image Generate with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Image Generate AI skill free?

Yes. It is published on GitHub by Prismer-AI under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇