Automation & AI prompts
Two settings let a team shape ContentsVision's output without code: auto-approval rules (which items get approved automatically) and custom prompt add-ons (extra instructions layered onto the AI's built-in prompt). Both are stored as JSON files on disk (not in the database) and edited from the Settings page.
Settings are scoped per team. Each team has its own pair of files under storage/team_settings/<team_id>/ (automation_settings.json and prompt_settings.json), so one team's rules and prompt add-ons never affect another team's. The API reads and writes the file for the team on the caller's auth token; the pipeline resolves a job's owning team (job → room → claim → team_id) and loads that team's settings.
Before settings were team-scoped there was a single global file per type at storage/automation_settings.json and storage/prompt_settings.json. Those are still read as a fallback when a team has no file of its own yet, so previously-global configuration keeps applying until that team next saves (which writes its own per-team file). New saves never write the legacy files.
Auto-approval rules
Reviewing every item by hand is slow. Auto-approval clears the obvious ones so reviewers focus on the rest. The rules live in services/auto_approve.py.
The rule schema
class AutomationSettings:
enabled: bool = False # master switch
run_on_complete: bool = True # run automatically when a job finishes
min_confidence: float = 0.80 # item confidence must be >= this
allowed_conditions: list = ["Good", "Fair"] # condition must be in this list (empty = any)
skip_flagged: bool = True # never auto-approve flagged items
How an item is judged
ALL enabled checks must pass for an item to be approved. The logic (item_passes_rules) is intentionally simple:
When it runs
- Automatically: if
enabledandrun_on_completeare true, every pipeline runs auto-approve as its last step, so a finished job arrives with the safe items already approved. - On demand:
POST /api/inventory/{job_id}/auto-approveapplies the saved rules to a job's still-unapproved items. Auto-approve only flipsapprovedfrom false to true, so it is safe to re-run and easy to undo from the activity log.
Custom AI prompts
A team can bolt small, specific instructions onto the AI's built-in prompt per media type, for example "never return refrigerators" or "always add an item called 'wooden bench'". This is in services/prompt_settings.py.
The splice model
The built-in prompt is not editable. It carries the mechanics (how to find, name, and judge items) and ends with a locked OUTPUT FORMAT: block that the rest of the app parses. A team's add-on is spliced between the built-in instructions and that locked block, so the JSON contract is always preserved.
With no add-on, the effective prompt is byte-for-byte the built-in default. An add-on must be between 3 and MAX_ADDITIONAL_CHARS (2000) characters, a product guardrail that keeps it a small customization.
Media types and presets
There are four customizable prompt types, matching the pipelines:
| Type | Used by |
|---|---|
video | The video pipeline. |
photo_merged | A photo group the user combined as one item. |
photo_unmerged | A lone, ungrouped photo. |
audio | The audio pipeline. |
Per type, a team keeps a library of named presets plus the always-available built-in default. One preset is marked active (active_id); new jobs of that type use the active one. A job already running keeps the prompt it started with, because each pipeline reads its effective prompt once at the top of the run.
Saving and the activity log
PUT /api/settings/prompts validates the settings (unique ids, non-empty names, length bounds, a valid active id) and, on save, computes a human-readable diff of exactly what changed (created, renamed, edited, deleted, turned on or off) and writes it to the activity log. So "Now using Video add-on 'No appliances' for new jobs" shows up as a real, readable history entry.
Prompt and rule changes affect new jobs only. To apply a new prompt to an existing upload, re-process it.