# Integrated Source-Agent mode The same `neural-brain` binary and Docker image now has two runtime roles: ```env BRAIN_MODE=brain ``` starts the full graph/AI application, while ```env BRAIN_MODE=agent ``` starts only the distributed source poller. Agent mode does **not** initialize the graph, Ollama, SearXNG, GLPI sync, AI-THINK or article synthesis. ## Brain-side flow The Brain owns Agent identities, source tasks and the Source Inbox in `source-agents.db`. 1. Open `/source-agents.html`. 2. Create an Agent. The plaintext token is returned exactly when it is created or rotated; only its SHA-256 hash is stored by the Brain. 3. Add RSS, Atom, sitemap or generic Web tasks and a polling interval. 4. The remote Agent obtains its task list from `GET /api/v1/agent/config`. 5. New documents are sent in batches to `POST /api/v1/agent/ingest`. 6. Documents enter the Inbox as `received`, not as graph nodes. 7. The Brain embeds a bounded Inbox batch and checks it against the existing KB. Relevant documents become `candidate`; weak matches become `archived`. 8. Adaptive article/reviewer research queries the `candidate` Inbox before SearXNG. For freshness-sensitive requests, only sufficiently recent Inbox documents are reused. 9. A Web document becomes a graph node only when a generated article actually grounds a supported claim in it. Then the Inbox row becomes `used`. This deliberately separates `discovered` from `knowledge`. ## Agent bootstrap Minimal remote Agent configuration: ```env BRAIN_MODE=agent BRAIN_AGENT_BRAIN_URL=https://brain.example.org BRAIN_AGENT_ID=security-news-01 BRAIN_AGENT_TOKEN=brain_agent_... ``` Optional Agent settings: ```env BRAIN_AGENT_CONFIG_REFRESH=5m BRAIN_AGENT_HTTP_TIMEOUT=30s BRAIN_AGENT_CONCURRENCY=3 BRAIN_AGENT_BATCH_SIZE=50 BRAIN_AGENT_ALLOW_PRIVATE=false ``` The Agent caches the last successful remote task configuration in its data volume. Source polling uses SSRF-safe DNS/redirect handling and rejects private, loopback and link-local targets by default; set `BRAIN_AGENT_ALLOW_PRIVATE=true` only for intentionally trusted intranet sources. This restriction applies to source URLs, not to the Brain control-plane URL, so the Brain itself may live on a private LAN. A local bootstrap JSON can be used instead of the three connection ENV values: ```json { "brain_url": "https://brain.example.org", "agent_id": "security-news-01", "token": "brain_agent_..." } ``` and: ```env BRAIN_MODE=agent BRAIN_AGENT_CONFIG_FILE=/run/secrets/brain-agent.json ``` ## Source task schema Example task returned by the Brain: ```json { "id": "microsoft-security", "agent_id": "security-news-01", "name": "Microsoft Security", "type": "rss", "url": "https://example.org/feed.xml", "enabled": true, "poll_interval": "2h", "categories": ["Microsoft", "Security"], "max_items": 20, "config": { "refetch_seen": "false" } } ``` Supported task types in v1 are `rss`, `atom`, `sitemap` and `web`. Set `config.refetch_seen=true` for sources whose existing URLs are expected to change (for example rolling advisories). Otherwise the Agent optimizes for discovery of new article URLs. ## Agent API permissions Agent Bearer tokens are accepted only on: - `GET /api/v1/agent/config` - `POST /api/v1/agent/heartbeat` - `POST /api/v1/agent/ingest` - `GET /api/v1/agent/compute/claim` - `POST /api/v1/agent/compute/{id}/result` They are separate from `BRAIN_API_KEY` and do not authorize graph, runtime, research, THINK or administration APIs. Agent-management and Source-Inbox management endpoints use the normal `BRAIN_API_KEY` whenever it is configured. ## Source Inbox tuning Brain-side defaults: ```env BRAIN_SOURCE_INBOX_ENABLED=true BRAIN_SOURCE_INBOX_INTERVAL=30s BRAIN_SOURCE_INBOX_BATCH_SIZE=12 BRAIN_SOURCE_INBOX_MIN_SIMILARITY=0.55 BRAIN_SOURCE_INBOX_MIN_PRIORITY=0.55 BRAIN_SOURCE_INBOX_NOVELTY_FLOOR=0.35 BRAIN_SOURCE_INBOX_MIN_RESULTS=2 BRAIN_SOURCE_INBOX_FRESH_MAX_AGE=168h ``` Classification is deliberately cheap: one batched embedding operation plus the configured precise/clustered nearest-neighbour retrieval and deterministic freshness/task/advisory scoring. There is no Gemma/Qwen call just to classify every incoming news item. ## Docker `deployment/docker-compose.source-agent.yml` is a minimal example that builds the exact same project with `BRAIN_MODE=agent`. The Agent only needs a persistent `/app/data` volume for local dedupe state and its cached remote configuration. ## Verbindungsdiagnose und Docker-Adressen Ein Agent registriert sich aus Sicherheitsgründen **nicht selbst**. Er muss zuerst im Brain unter `/source-agents.html` angelegt werden; dort entsteht der Token. Ein Agent darf bereits Tasks zugewiesen bekommen, bevor er das erste Mal online ist. `BRAIN_AGENT_BRAIN_URL=http://127.0.0.1:...` oder `localhost` ist bei einem separaten Docker-Container fast immer falsch: Loopback zeigt auf den Agent-Container selbst. Für einen Agent auf demselben Docker-Host kann stattdessen `http://host.docker.internal:` verwendet werden. Auf einem gemeinsamen Docker-Netz ist der Brain-Service-Name vorzuziehen. Das Brain kann mit `BRAIN_PUBLIC_URL` die korrekte, aus Agent-Sicht erreichbare Adresse veröffentlichen. Das Webinterface verwendet diese Adresse beim Erzeugen/Rotieren von Tokens. Der Agent stellt auf `/` eine kleine Statusseite und auf `/api/status` Diagnosedaten bereit. `brain_connected`, `last_config_success_at`, `last_heartbeat_success_at` und `last_connection_error` zeigen die tatsächliche Verbindung; `config_issued_at` kann dagegen aus dem lokalen Cache stammen und ist allein kein Verbindungsnachweis. Das Agent-Compose veröffentlicht die Statusseite standardmäßig über `BRAIN_AGENT_PORT=8092`. ### Inbox-Klassifizierung für News und Advisories Seit Classifier v2 ist `BRAIN_SOURCE_INBOX_MIN_SIMILARITY` kein alleiniger Ausschlussfilter mehr. Ein Dokument wird `candidate`, wenn es entweder direkt genug KB-Nähe erreicht oder oberhalb des Novelty-Floors durch einen kombinierten Prioritätsscore aus KB-Nähe, kuratiertem Task-/Quellenkontext, Aktualität und News-/Advisory-Signalen relevant bleibt. - `BRAIN_SOURCE_INBOX_MIN_SIMILARITY=0.55`: direkte semantische Übernahme als Candidate. - `BRAIN_SOURCE_INBOX_MIN_PRIORITY=0.55`: Mindestscore des kombinierten News-/Knowledge-Routings. - `BRAIN_SOURCE_INBOX_NOVELTY_FLOOR=0.35`: harte Mindestnähe zur KB; darunter bleibt auch ein frischer Security-Alert archiviert. Beim ersten Start einer neuen Classifier-Version werden bereits archivierte Dokumente einmalig auf `received` zurückgesetzt und mit der aktuellen Logik neu klassifiziert. Classifier v3 ergänzt dabei die proaktive Security-Ausnahme; bestehende `candidate`-Security-Meldungen werden beim Start ebenfalls einmalig für die Security-Queue erkannt. ## Proaktive Security-/Advisory-Verarbeitung Ab Classifier v3 gibt es bewusst zwei Inbox-Pfade: - Normale `candidate`-Dokumente bleiben passiv und werden erst bei einem konkreten Evidenzbedarf vor SearXNG durchsucht. - Security-/Advisory-/CVE-Candidates können proaktiv verarbeitet werden. Die Erkennung nutzt den kuratierten Task-/Quellenkontext und starke Security-/Advisory-Signale; pro Task kann sie im Webinterface auf `auto`, `proaktiv` oder `passiv` gesetzt werden. Brain-seitige Defaults: ```env BRAIN_SOURCE_INBOX_SECURITY_PROACTIVE=true BRAIN_SOURCE_INBOX_SECURITY_BATCH_SIZE=2 BRAIN_SOURCE_INBOX_SECURITY_MIN_PRIORITY=0.58 BRAIN_SOURCE_INBOX_SECURITY_MIN_CONFIDENCE=0.72 BRAIN_SOURCE_INBOX_SECURITY_FETCH_MIN_CHARS=1800 BRAIN_SOURCE_INBOX_SECURITY_RESEARCH_RESULTS=3 ``` Der proaktive Ablauf ist begrenzt und quellengebunden: 1. Der Agent liefert RSS-/Atom-/Web-Volltext und markiert den Task-Modus mit `security_proactive`. 2. Ein ausreichend priorisierter Security-Candidate wird in eine kleine Security-Queue gestellt, behält aber bis zur Materialisierung den öffentlichen Status `candidate`. 3. Ist der Agent-Text kürzer als `BRAIN_SOURCE_INBOX_SECURITY_FETCH_MIN_CHARS` oder war der ursprüngliche Fetch fehlerhaft, lädt das Brain die kanonische Artikel-URL noch einmal direkt mit den Research-SSRF-Regeln. 4. Gemma (das konfigurierte `BRAIN_ARTICLE_SYNTHESIS_MODEL`) extrahiert ausschließlich aus den gelieferten Quellen einen strukturierten Security-Faktensatz: Ereignistyp, Vendor/Produkte, CVEs, betroffene/fixe Versionen, konkrete Fakten und Maßnahmen. Parametrisches Modellwissen darf fehlende Angaben nicht ergänzen. 5. Meldet Gemma `research_needed=true`, werden höchstens zwei präzise Suchfragen über SearXNG ausgeführt und insgesamt maximal `BRAIN_SOURCE_INBOX_SECURITY_RESEARCH_RESULTS` zusätzliche Volltexte geladen. Danach bewertet Gemma den Faktensatz erneut. 6. Nur bei `security_relevant=true`, `materialize=true`, ausreichender Confidence und mindestens einem konkreten Fakt entsteht ein `external`-Node mit `validation_state=security_verified`, Origin `source-agent-security` und einer `security_update_for`-Kante zum semantisch passendsten KB-Node. 7. Der Inbox-Status wird `materialized`. Das Dokument bleibt weiterhin als lokale Evidenz vor SearXNG auffindbar. Wird es später von einem akzeptierten Artikel-Claim zitiert, wechselt es wie bisher auf `used`. Damit ist eine kuratierte Security-Quelle ein priorisierter, bestätigter Discovery-Kanal, aber kein Freibrief für unbelegte CVE-/Versions-/Severity-Angaben. Normale News-/Dokumentationsquellen behalten weiterhin den ressourcenschonenden passiven Candidate-Pfad. ## Crash-Recovery und genaue Provenienz Security-Lifecycles werden im Source-Inbox-Store persistiert. Nach einem Neustart werden verwaiste `processing`-Claims sofort freigegeben. Meldet der Store `materialized`, der deterministische Security-Node fehlt aber nach einem harten Abbruch im Graph, wird der Eintrag automatisch requeued und idempotent neu materialisiert. Inbox-Evidenz trägt eine `source_inbox_id`. Späteres Claim-Grounding setzt damit exakt die tatsächlich verwendete Content-Version auf `used`; ältere Revisionen derselben URL werden nicht mehr pauschal mitmarkiert. ## CPU compute jobs (`vector_graph`) An integrated Source Agent can also act as a model-free CPU worker. This is independent of RSS/Web polling tasks: an Agent with zero source tasks can still advertise and execute `vector_graph` jobs. Enable on the Agent: ```env BRAIN_AGENT_COMPUTE_ENABLED=true BRAIN_AGENT_COMPUTE_POLL_INTERVAL=5s BRAIN_AGENT_COMPUTE_MAX_BYTES=134217728 ``` Enable offload on the Brain: ```env BRAIN_VECTOR_GRAPH_ENABLED=true BRAIN_VECTOR_GRAPH_AGENT_OFFLOAD=true BRAIN_VECTOR_GRAPH_AGENT_REQUIRED=false BRAIN_VECTOR_GRAPH_AGENT_WAIT=2m ``` The Agent receives already existing embeddings and performs deterministic LSH/k-NN/Cosine/local-scaling arithmetic. It does not start or call Ollama. Results are accepted only for the claimed job and are validated by the Brain before the Brain persists `semantic_neighbor` edges. With `BRAIN_VECTOR_GRAPH_AGENT_REQUIRED=false`, unavailable/stale/failed remote jobs automatically fall back to the identical local CPU implementation. Agent tokens now additionally authorize only these compute endpoints: - `GET /api/v1/agent/compute/claim` - `POST /api/v1/agent/compute/{id}/result` The claim endpoint requires the Agent to have advertised the `vector_graph` capability in its heartbeat. These endpoints still do not authorize graph administration, THINK, research or runtime settings. See `VECTOR-GRAPH-AGENT-OFFLOAD-V3.md` for the protocol and security boundaries. ## v8: modellfreie Artikelprüfung Ein Agent mit aktiviertem Compute-Worker meldet nun zwei CPU-Capabilities: `vector_graph` und `article_quality`. `article_quality` berechnet ausschließlich deterministische Struktur-, Redundanz-, Evidenzabdeckungs- und Informationsdichte-Metriken. Es werden weder Ollama noch Embeddings oder Chatmodelle aufgerufen. Das Brain rekonstruiert Pass/Fail und Rewrite-Empfehlungen aus festen Regeln und bleibt damit Owner der Qualitätsentscheidung. ## Docker-Controller-Rolle (v9) Die Controller-Rolle ist eine zusätzliche, explizit freizugebende Agent-Capability. `BRAIN_AGENT_DOCKER_CONTROLLER_ENABLED=true` allein genügt nicht: Das Brain muss zusätzlich die zentrale Controller-Policy aktivieren. Der normale Source-Agent-Compose mountet Docker.sock absichtlich nicht; dafür existiert `deployment/docker-compose.controller-agent.yml` als Opt-in-Override. Der Agent meldet `docker_controller` und, falls verfügbar, `docker_compose`. Autonome Jobs kommen ausschließlich aus freigegebenen Controller-Profilen; der Agent führt keine beliebigen vom LLM erzeugten Shell-Kommandos aus. Siehe `DOCKER-CONTROLLER-V9.md`.