Create a Prompt
Define reusable LLM instruction templates that can be versioned, scoped, and shared across plugins.
Prompts are reusable LLM instruction templates stored in the platform. Instead of hardcoding prompt strings in your plugin code, you register prompts separately and load them at runtime with self.get_prompt(). This lets you update prompts without redeploying plugins, share prompts across teams, and manage prompt versions independently.
What Prompts Are
A prompt is a named text template with {{PLACEHOLDER}} markers that gets resolved at runtime. Prompts are stored in the platform and loaded by plugins using self.get_prompt(name). They are not executable on their own — they are inputs to the prompt_llm() service method.
- Centralized — all prompt logic lives in one place, separate from plugin code
- Versioned — the platform tracks prompt history so you can roll back to a previous version
- Scoped — prompts can be user-level, tenant-level, or global, controlling who can access and modify them
- Testable — update and test prompts without rebuilding or redeploying plugins
Benefits
| Benefit | Without Prompts | With Prompts |
|---|---|---|
| Update LLM instructions | Modify plugin code, rebuild, redeploy | Update the prompt via API — takes effect immediately |
| Share across plugins | Copy-paste prompt strings between plugins | Both plugins call self.get_prompt("shared-classifier") |
| A/B testing | Deploy two plugin versions | Create two prompts, switch the name in pipeline config |
| Rollback | Redeploy the previous plugin version | Revert the prompt to a previous version via API |
| Audit trail | Check git history for prompt changes | Platform tracks who changed what and when |
Step 1 — Write the Template
Write your prompt template as a text string with {{PLACEHOLDER}} markers for dynamic content. Placeholders are replaced by your plugin code at runtime before being sent to the LLM.
You are a document classification expert.
Analyze the following document and classify it as exactly one of:
{{CATEGORIES}}
Document filename: {{FILENAME}}
Document content:
{{DOCUMENT_CONTENT}}
Rules:
1. Respond with ONLY the document type label.
2. Do not include any explanation or punctuation.
3. If the document does not match any category, respond with "unknown".Use descriptive placeholder names that make the template self-documenting. Avoid generic names like {{INPUT}} or {{DATA}} — prefer {{DOCUMENT_CONTENT}}, {{FIELD_DEFINITIONS}}, {{CATEGORIES}}.
Step 2 — Choose a Scope
Prompts have three scope levels that control visibility and access:
| Scope | Visibility | Who Can Edit | Use Case |
|---|---|---|---|
| user | Only the creating user | The creating user only | Personal experimentation and testing |
| tenant | All users in the tenant (organization) | Tenant admins | Shared across a team or organization — most common |
| global | All users on the platform | Platform admins only | System-wide defaults provided by bizSupply |
When a plugin calls self.get_prompt("name"), the platform resolves scope in order: user -> tenant -> global. A user-scoped prompt with the same name as a tenant-scoped prompt will take precedence for that user.
Step 3 — Register via the API
Register the prompt using the POST /prompts endpoint:
curl -X POST https://api.bizsupply.com/v1/prompts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "financial-doc-classifier",
"scope": "tenant",
"description": "Classifies financial documents into standard categories.",
"template": "You are a document classification expert.\n\nAnalyze the following document and classify it as exactly one of:\n{{CATEGORIES}}\n\nDocument filename: {{FILENAME}}\n\nDocument content:\n{{DOCUMENT_CONTENT}}\n\nRules:\n1. Respond with ONLY the document type label.\n2. Do not include any explanation or punctuation.\n3. If the document does not match any category, respond with \"unknown\"."
}'The API returns the registered prompt:
{
"id": "pmt_x7y8z9",
"name": "financial-doc-classifier",
"scope": "tenant",
"version": 1,
"description": "Classifies financial documents into standard categories.",
"template": "You are a document classification expert...",
"created_by": "usr_abc123",
"created_at": "2026-01-15T10: 30: 00Z",
"updated_at": "2026-01-15T10: 30: 00Z"
}Step 4 — Verify
Confirm the prompt was registered by retrieving it:
curl -X GET https://api.bizsupply.com/v1/prompts/financial-doc-classifier \
-H "Authorization: Bearer YOUR_API_KEY"
="color:#5c6370;font-style:italic"># Response:
="color:#5c6370;font-style:italic"># {
="color:#5c6370;font-style:italic"># "id": "pmt_x7y8z9",
="color:#5c6370;font-style:italic"># "name": "financial-doc-classifier",
="color:#5c6370;font-style:italic"># "version": 1,
="color:#5c6370;font-style:italic"># "template": "You are a document classification expert..."
="color:#5c6370;font-style:italic"># }Step 5 — Use in Plugins
Load the prompt in your plugin using self.get_prompt() and replace the placeholders with runtime values before sending to the LLM.
from bizsupply_sdk import ClassificationPlugin
class FinancialClassifier(ClassificationPlugin):
name = "financial-classifier"
version = "1.0.0"
CATEGORIES = [
"invoice", "purchase_order", "receipt",
"contract", "credit_note", "unknown",
]
def classify(self, document) -> str:
# Load the prompt template from the platform
template = self.get_prompt("financial-doc-classifier")
# Replace placeholders with runtime values
prompt = template.replace(
"{{CATEGORIES}}",
"\n".join(f"- {cat}" for cat in self.CATEGORIES),
).replace(
"{{FILENAME}}",
document.filename,
).replace(
"{{DOCUMENT_CONTENT}}",
document.content[:4000],
)
# Send to the LLM
result = self.prompt_llm(prompt, temperature=0.1)
doc_type = result.strip().lower().replace(" ", "_")
if doc_type not in set(self.CATEGORIES):
return "unknown"
return doc_typeIf the prompt name does not exist, self.get_prompt() raises a PluginError. Always register the prompt before deploying the plugin, or wrap the call in a try/except to fall back to a default prompt.
Management Operations
Get a Prompt
="color:#5c6370;font-style:italic"># Get latest version
curl -X GET https://api.bizsupply.com/v1/prompts/financial-doc-classifier \
-H "Authorization: Bearer YOUR_API_KEY"
="color:#5c6370;font-style:italic"># Get a specific version
curl -X GET https://api.bizsupply.com/v1/prompts/financial-doc-classifier?version=2 \
-H "Authorization: Bearer YOUR_API_KEY"
="color:#5c6370;font-style:italic"># List all prompts
curl -X GET https://api.bizsupply.com/v1/prompts \
-H "Authorization: Bearer YOUR_API_KEY"
="color:#5c6370;font-style:italic"># List prompts filtered by scope
curl -X GET "https://api.bizsupply.com/v1/prompts?scope=tenant" \
-H "Authorization: Bearer YOUR_API_KEY"Update a Prompt
Updating a prompt creates a new version. The previous version is preserved in history.
curl -X PUT https://api.bizsupply.com/v1/prompts/financial-doc-classifier \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "You are a senior document analyst...\n\n(updated template here)",
"description": "Updated with improved classification accuracy."
}'
="color:#5c6370;font-style:italic"># Response includes the new version number:
="color:#5c6370;font-style:italic"># { "version": 2, "updated_at": "2026-02-01T14:00:00Z" }Delete a Prompt
curl -X DELETE https://api.bizsupply.com/v1/prompts/financial-doc-classifier \
-H "Authorization: Bearer YOUR_API_KEY"
="color:#5c6370;font-style:italic"># Response: { "deleted": true }Deleting a prompt will cause any plugin that calls self.get_prompt("financial-doc-classifier") to fail with a PluginError. Make sure no active plugins reference the prompt before deleting.
Common Patterns
Classification Prompt
You are a document classification expert.
Analyze the following document and classify it as exactly one of:
{{CATEGORIES}}
Document filename: {{FILENAME}}
Document content:
{{DOCUMENT_CONTENT}}
Respond with ONLY the document type label. No explanation.Extraction Prompt
You are a document extraction expert.
Extract the following fields from this {{DOCUMENT_TYPE}} document:
{{FIELDS}}
Document content:
{{DOCUMENT_CONTENT}}
Rules:
1. Return ONLY a JSON object with field names as keys.
2. For each field, also include a {field_name}_confidence key with a value from 0.0 to 1.0.
3. If a field cannot be found, set its value to null.
4. For date fields, use ISO 8601 format (YYYY-MM-DD).
5. For number fields, return raw numbers without currency symbols or commas.Contract Analysis Prompt
You are a contract analysis expert specializing in {{CONTRACT_TYPE}} agreements.
Analyze the following contract and extract:
{{FIELDS}}
Pay special attention to:
- Renewal clauses and auto-renewal terms
- Termination conditions and notice periods
- Pricing escalation clauses
- Liability caps and indemnification
Contract content:
{{DOCUMENT_CONTENT}}
Return a JSON object with the extracted fields. Include a "risk_flags" array with any concerning clauses identified.Next Steps
- Create a Classification Plugin that loads prompts with self.get_prompt().
- Create an Extraction Plugin with a separate extraction prompt template.
- Create a Pipeline to wire your prompt-powered plugins into a processing flow.
- Read the Plugin Service API Reference for details on prompt_llm() and get_prompt().