All pages

SingGuard guard server

Judges an image or a prompt against a written policy and returns a verdict and the rule that fired. Darkroom will not start without one. The server is agent-composer's /api/guard/check, running the SingGuard model on Ollama.

Used by

PackageWhat forReads
argus-darkroom (opens in new tab)

Required. Pre-flight (text-only) and per-policy image scans. Default mode cascade.

ARGUS_DARKROOM_SINGGUARD_URL, ARGUS_DARKROOM_THINKING, --thinking

argus-curator (opens in new tab)

Policy check and --guard-* scan filters. Off when the URL is unset.

ARGUS_CURATOR_SINGGUARD_URL, ARGUS_CURATOR_SINGGUARD_THINKING, ARGUS_CURATOR_SINGGUARD_POLICY_FILE, ARGUS_CURATOR_SINGGUARD_CONTEXT, ARGUS_CURATOR_SINGGUARD_TIMEOUT, ARGUS_CURATOR_SINGGUARD_WORKERS

argus-cortex (opens in new tab)

SingGuardClient, GuardResult, THINKING_MODES, and the policy texts.

—

Official guides

Which server

The suite's clients speak one API: POST /api/guard/check. Two servers implement it:

  • agent-composer's guard (recommended). It is the /api/guard/* router inside agent-composer's rag-chat service, on port 9150. It runs SingGuard on Ollama and supports all four thinking modes, for images and for text-only checks. Darkroom needs this one, because its pre-flight is a text-only check.
  • argus-cull's singguard service (profile local-singguard, also on 9150). It supports all four modes too, but it checks images only, so it can't serve darkroom's pre-flight. It shouldn't run beside agent-composer.

Any other SingGuard deployment offers only the model's own fast and fast-slow modes.

The rest of this page sets up agent-composer's guard.

Minimal setup

The guard needs a GPU host with Docker and the NVIDIA Container Toolkit (see GPU host).

  1. Clone agent-composer (opens in new tab) and copy .env.example to .env.

  2. rag-chat won't start without a vector store and a database, even if you only want the guard. Set QDRANT_URL and DATABASE_URL in .env, pointing at instances you already run or at new ones. To set them up, see the PostgreSQL downloads (opens in new tab) or the Postgres Docker image (opens in new tab), and the Qdrant quickstart (opens in new tab). A two-command local setup is on Postgres, Qdrant and MinIO.

  3. Start the stack: docker compose up -d --build. Ollama starts with it.

  4. Pull the model into that Ollama once:

    docker exec ollama ollama pull hf.co/inclusionAI/SingGuard-4b-GGUF:Q4_K_M
    

    That is the default GUARD_MODEL. The same Hugging Face repo also has Q8_0 and F16 builds, and there are 0.8b, 2b and 8b sizes. The 0.8b repo is spelled Sing-Guard-0.8b-GGUF. To use another one, set GUARD_MODEL to its hf.co/… tag and pull it the same way.

  5. Check it: curl http://localhost:9150/health. There is also a tester page at /ui/guard.

  6. Point the clients at it, for example ARGUS_DARKROOM_SINGGUARD_URL=http://<GPU_HOST>:9150. In Studio's compose, set DARKROOM_SINGGUARD_URL (or SINGGUARD_URL) for darkroom and ARGUS_CURATOR_SINGGUARD_URL for curator. Each is the origin only: the clients add /api/guard/check themselves.

The guard routes have no authentication. The port binds to 127.0.0.1 by default (RAG_CHAT_BIND_IP, RAG_CHAT_PORT). Widen it only to a trusted network, or put it behind an access proxy.

Server settings

VariableDefaultMeaning
GUARD_MODELhf.co/inclusionAI/SingGuard-4b-GGUF:Q4_K_MThe Ollama model tag. A request's own model field overrides it.
GUARD_THINKINGfast-slowMode used when a request leaves thinking blank. An invalid value falls back to fast-slow.
GUARD_WORKER_CONCURRENCY1Guard passes run one at a time across all callers.
OLLAMA_URLhttp://ollama:11434The Ollama the guard calls.
OLLAMA_KEEP_ALIVE15mHow long Ollama keeps the model loaded.
OLLAMA_TIMEOUT300Seconds before a guard call to Ollama gives up.

For text checks the server renders SingGuard's chat template itself and calls Ollama's /api/generate in raw mode, because Ollama doesn't pass the template's policy argument through. Image checks go through /api/chat. Sampling is fixed at temperature 0.

The check endpoint

POST /api/guard/check, JSON body:

FieldMeaning
inputThe text to judge. With an image, the prompt that produced it.
image_base64Optional. Raw base64 or a data URL. It is downscaled to at most 1536 px and 4 MiB.
conversationOptional list of {role, content} turns, for chat context.
input_roleuser (default) or assistant.
policyMarkdown rules. Blank means SingGuard's default rules. Each rule is a ### heading under ## Risk Categories, which the server adds if it's missing.
thinkingfast, fast-slow, slow or cascade. Blank means GUARD_THINKING.
modelOptional model override.

Response:

FieldMeaning
safetrue or false.
verdictThe model's verdict line.
rule, rule_textThe title and text of the rule that fired.
explanationThe model's reason.
categories[{code, label, why}], empty when safe. Cortex reads the fired rules from code.
thinkingThe mode actually used. A cascade check reports fast or slow.
model, elapsed_ms, rawDiagnostics.

Errors: 400 for an unknown mode or a bad image, 503 when Ollama is unreachable, and Ollama's own status otherwise. Every client treats an error or a missing verdict as unchecked, never as safe (see the limits).

GET /api/guard/categories lists the default rules, and GET /api/guard/policy returns the default policy, the default mode and the list of modes.

Policies

The server keeps only SingGuard's defaults. The named policies (default, adult, adult-granular, adult-cautious, adult-cinematic) are texts in cortex's policies.py (opens in new tab), and each client sends the full text with every request. Curator can also read one from a file (ARGUS_CURATOR_SINGGUARD_POLICY_FILE). See Moderation for what the adult policies change.