Appearance
Use AI Studio from your plugin, the CLI, the SDK and MCP
What you're doing
AI Studio is where a workspace builds its AI: model profiles, prompts, knowledge bases, RAG pipelines, agents and evaluations. Everything in it is a plain definition with a code, versions and labels, so a plugin can ship it, and any code can call it.
This guide shows the four ways to use it from a plugin-based application:
- Ship AI assets inside your plugin, so every tenant that installs it gets them.
- Call them from plugin workflows and services.
- Drive it from the
erpCLI and your AI coding agent (MCP). - Call it from any code with an OpenAI-compatible SDK and an app API key.
The model is never named in your plugin. You refer to a model profile such as default, and each tenant decides which real model, key and fallback sit behind it.
1. Ship AI assets in your plugin
Put one JSON file per asset under spk-assembly/metadata/:
| Folder | What it is | Schema name |
|---|---|---|
prompt/<code>.json | a prompt with {{variables}} | ai-prompt |
rag/<code>.json | a RAG pipeline (how to answer from knowledge) | ai-rag-pipeline |
eval/<code>.json | test questions and scorers | ai-eval-dataset |
knowledge/<code>.json | documents to search | ai-knowledge-base |
agent/<code>.json | an agent (tools, knowledge, guardrails) | ai-agent |
A prompt, metadata/prompt/summarise-policy.json:
json
{
"promptCode": "summarise-policy",
"name": "Summarise a policy",
"systemTemplate": "You explain HR policies in plain language.",
"userTemplate": "Summarise this policy in three bullet points:\n\n{{document}}",
"profileCode": "default",
"labels": ["prod"]
}A RAG pipeline, metadata/rag/hr-qa.json, that answers from the plugin's own knowledge base:
json
{
"pipelineCode": "hr-qa",
"name": "HR policy answers",
"definition": {
"retrieve": { "knowledgeBases": ["hr-policies"], "mode": "HYBRID", "topK": 5 },
"generate": { "profileCode": "default" },
"noAnswerText": "I could not find this in the HR policies."
},
"labels": ["prod"]
}An agent, metadata/agent/hr-helper.json, that takes its instructions from the prompt library and checks requests for prompt injection:
json
{
"agentCode": "hr-helper",
"name": "HR helper",
"instructions": "Answer HR questions from the policies.",
"instructionsPrompt": "hr-helper-brief@prod",
"autonomyLevel": "READ",
"modelProfile": "default",
"knowledgeSources": ["hr-policies"],
"guardrails": { "input": { "enabled": true, "checks": ["injection"], "action": "block" } }
}What happens on install and on upgrade
- A new prompt or pipeline is created as version 1 with the labels you list (default
prod). - On an upgrade with changed content a new version is added. A label moves to it only if it still points at a version your plugin installed. If the tenant took the label over (they edited the prompt and moved
prod), their choice is never overwritten; the new version is offered as the labelplugin-latestinstead. - Evaluation datasets are created once. Tenants add their own cases.
- An agent's
instructionsPromptandguardrailsapply when the agent is new or has none set yet. - One malformed file is skipped and logged. It never stops the rest of the install.
Add them from Plugin Studio, the CLI or MCP
- Plugin Studio: open your plugin, find Prompts, RAG pipelines, Evaluations, AI agents or Knowledge bases in the Explorer and choose + Add. Pick Copy from AI Studio to bring in something you already built and tested, or Start from a template.
- CLI:
erp plugin op add-ai-asset --pluginId hr-assistant --kind prompt --code summarise-policy --source workspace - MCP: ask your coding agent to call
erp_plugin_opwithadd-ai-asset(same arguments).
Check the files
bash
erp schema validate spk-assembly/metadata/prompt/summarise-policy.json --schema ai-prompt
erp schema validate spk-assembly/metadata/agent/hr-helper.json --schema ai-agentThe CLI checks required fields and allowed values. The install itself also checks codes (lowercase letters, digits and dashes).
2. Call AI from plugin workflows and services
In a workflow, add AI steps as service tasks. They read earlier results with a whole-value token such as ${context.<taskKey>.<field>} (letters, digits and underscores only) and return typed fields for later conditions:
json
{
"taskKey": "analyze",
"stage": "review",
"kind": "service",
"taskType": "ai.classify",
"payload": { "code": "exit-risk", "label": "prod", "values": { "reason": "${context.get_employee.reason}" } }
}The task types are ai.prompt, ai.classify (the prompt answers in JSON), ai.retrieve, ai.rag, ai.agent and ai.guardrail. In Studio's Workflow Designer they are in the Add task list under AI. The workflow engine keeps control of the path; the AI step does one bounded thing.
In a Service-mode plugin (Python, Node.js or Go), the scaffold from erp service-plugin:scaffold includes an AI helper. Set ERP_AI_BASE_URL and ERP_AI_KEY, then:
python
from app.ai import run_prompt, ask
summary = run_prompt("summarise-policy", {"document": text})
result = ask("hr-qa", "How many leave days do I get?") # {"answer": "...", "citations": [...]}ts
import { runPrompt, ask } from "./ai";
const summary = await runPrompt("summarise-policy", { document: text });
const { answer, citations } = await ask("hr-qa", "How many leave days do I get?");go
// ai.go in the Go scaffold; the key decides the tenant, so no tenant id is passed
summary, err := RunPrompt(ctx, "summarise-policy", map[string]any{"document": text}, "prod")
result, err := Ask(ctx, "hr-qa", "How many leave days do I get?", "prod") // result.Answer, result.Citations3. Use it from the CLI and your AI coding agent
The same operations table drives erp plugin op <name> and the MCP tool erp_plugin_op, so a coding agent can work with a tenant's AI without any extra setup:
| Operation | What it does |
|---|---|
ai-prompts, ai-rag-list, ai-kb-list | list what the tenant has built |
ai-prompt-run | run a prompt (code, label, values) |
ai-rag-run | ask a pipeline a question, with citations and per-stage details |
ai-kb-query | search a knowledge base |
ai-eval-run | run an evaluation dataset against a prompt or pipeline label |
ai-usage | calls, tokens, latency and cost for the last N days |
ai-bundle-export, ai-bundle-import | move AI assets between tenants as one JSON bundle |
ai-keys, ai-key-create | manage app API keys |
The five schemas above are also served by erp_list_schemas and erp_get_schema, so an agent can write a valid prompt, pipeline or agent file the first time.
4. Call it from any code
Make an app API key (AI Studio, or erp plugin op ai-key-create --name "Billing app"). The secret starts with sk-spark-, is shown once, and decides the tenant. You can limit a key to certain models and a request rate. Then use any OpenAI SDK:
python
from openai import OpenAI
client = OpenAI(base_url="https://your-erp/api/v1/ai/openai/v1", api_key="sk-spark-...")
reply = client.chat.completions.create(model="default", messages=[{"role": "user", "content": "Say hello"}])model can be a profile code (default), a prompt (prompt:summarise-policy@prod, with the variables as JSON in the last message) or a RAG pipeline (rag:hr-qa@prod, the question in the last message; citations come back in a top-level citations field). /embeddings and /models work too.
How to verify it worked
- Install the plugin on a tenant, then open AI Studio. Your prompt, pipeline and agent are listed, with the
prodlabel. - In Prompts, run your prompt in the playground. In RAG pipelines, run a question and read what each stage did.
- Check Models > Usage. Your calls appear by source, for example
prompt:summarise-policy.
Common mistakes
- Naming a model in the plugin. Use a profile code. A vendor model name breaks on tenants that use another provider.
- Editing a shipped prompt in AI Studio and expecting an upgrade to replace it. By design a tenant's own
prodchoice wins; look forplugin-latest. - A pipeline that names a knowledge base the plugin does not ship. Ship it in
metadata/knowledge/, or make sure the tenant has it. - Sending a tenant id with an API key. The key already decides the tenant, and any tenant header is ignored.
What to read next
- Expose a plugin operation as an AI tool
- Build a Service-mode plugin in Python, Node.js or Go
- Use the MCP server with an AI agent
