AI (Phase 7)
CreatorOS uses Anthropic Claude for text and a placeholder renderer for graphics. Everything the AI creates is a draft: inactive products, status = draft posts, disabled automations, media assets flagged ai_generated. Publishing, activating, pricing and deleting always require a person in the dashboard.
Configuration
| Variable | Effect |
|---|---|
ANTHROPIC_API_KEY | Blank → MockAIProvider (deterministic, every output labelled "(mock)"), dashboard shows an amber banner. |
ANTHROPIC_MODEL | Model id sent to the Messages API (default claude-sonnet-5; claude-opus-5 recommended for copilot quality). |
IMAGE_PROVIDER | Only mock exists today (GD gradient + headline). Real provider is an open decision (CLAUDE.md §15). |
Plan limits: tenants.limits.ai_monthly (free 20 / creator 500 / network 5000). Each generation inserts one ai_usage row (tokens + estimated cost in micros); exceeding the limit returns HTTP 429 "AI limit reached". GET /dashboard/ai/usage shows the log.
Code map
app/Providers/AI/AIProvider.php— interface.AnthropicProvider(raw Messages API viaApp\Core\Http: system, adaptive thinking, tools +runTools()tool-result loop,output_config.formatJSON schema with prompt fallback, refusal handling).MockAIProviderfor keyless dev/test.app/Providers/AI/prompts/*.vN.md— versioned templates loaded byPromptLoaderwith{{var}}substitution. Bump the version suffix instead of editing a template in place.app/Providers/Image/—ImageProvider,MockImageProvider,Presets(ig_post, ig_story, facebook, tiktok, yt_thumb, discord_banner, twitch_panel, kick, x_header).app/Modules/AI/Services/AIService.php— bound as$app->make('ai'). Methods:complete,structured,generateContent,adaptPost(tenantId, body, providers),contentPlan,summarizeCreator,serverSetup,graphicsBrief,renderGraphic,copilot.app/Modules/AI/Services/CopilotTools.php— tool definitions and executors (all reads viaTenantScope; writes are drafts and audited).
Routes (auth + tenant + role:staff; POSTs throttled throttle:ai)
| Route | Purpose |
|---|---|
GET/POST /dashboard/copilot, POST /dashboard/copilot/reset | Chat copilot; conversation in session per tenant (last 20 turns). JSON in/out. |
GET/POST /dashboard/ai/content, POST /dashboard/ai/content/send | Content studio (captions, hashtags, titles, descriptions, CTAs, thumbnail text, short-form). ?plan=1 renders a 7-day plan. "→ Publisher" creates a draft post. |
GET/POST /dashboard/ai/graphics, GET /dashboard/ai/gallery | Preset-size graphics saved to storage + media_assets. |
GET /dashboard/onboarding-wizard, POST /dashboard/onboarding-wizard/{1-5} | Creator type → accounts → AI summary (Apply buttons) → community/server → "Launch your community" campaign drafts. |
GET/POST /dashboard/ai/server-setup, POST /dashboard/ai/server-setup/apply | Plain-language description → launch kit (VIP product inactive, posts draft, automation disabled, graphic, FAQ/rules proposals). |
GET /dashboard/ai/usage | Metering. |
Copilot tools
get_overview, list_products, analyze_sales (read-only) · create_draft_post, create_draft_product, generate_graphic, create_automation_draft (draft-only, staff role required, audited as ai.*). The system prompt (copilot.system.v1.md) instructs the model to refuse publish/price/refund requests and point at the dashboard.
Adding a real image provider
Implement ImageProvider::generate(prompt, width, height, opts) returning ['bytes','mime','width','height'], return it from AIService::imageProvider() based on config('providers.image.driver'), and add the credentials to .env.example.