Skip to content

Agents in NomOS

NomOS governs two kinds of agents: those it runs itself, and your own that you bring along. This page explains the difference and how you use both.

The difference is who runs the agent and how deeply NomOS controls it.

Internal agent

NomOS runs it (Bedrock, server-side). You configure the mission, tools, autonomy level, model, and budget. Every step goes through the full governance stack.

External agent

You run it (Hermes, Claude Desktop, your own program). NomOS gives it identity and rules and cooperatively governs what it submits through validate_action or ask_brain. On top of that comes the kill switch.

Think of it like this: internal = an employee the company hires and directs. External = an outside contractor with a visitor badge: access and house rules yes, payroll no.

Create an agent in the room (tab «Agents» → «Internal agents»): mission, tools (ask_brain), autonomy level (L0–L3), model, monthly budget. The inherited knowledge scope comes from the room.

Lifecycle: create → eval suite → approve → run → evidence. Only room owners (decision makers) can evaluate and approve. Each run produces a traceable evidence record (verdict, citations, costs). If the room constitution changes after approval, re-evaluation is required.

An external agent is a standalone program that performs tasks: reading files, writing code, handling tickets, calling APIs. It runs outside NomOS; you bring your own agent (Hermes, Claude Desktop, Codex, or your own). NomOS supplies the governance layer underneath.

The agent connects through MCP, queries NomOS for knowledge («ask_brain»), and submits planned actions for review («validate_action»). NomOS replies with a verdict (allow, caution, require_approval, or block) before the agent acts. This is cooperative governance: the agent calls the check voluntarily. The hard backstop is the kill switch (see the following sections).

Choose the type that fits your agent. The difference is the identity under which the agent acts:

Per-User

The agent acts in your name. It uses your OAuth identity and sees exactly the rooms you are a member of. Suitable for a personal copilot that mirrors your room access. Public client with PKCE: there is no secret, and the client ID is all the connecting client needs.

NHI (Non-Human Identity)

Non-human identity: the agent gets its own fixed machine identity, a Keycloak service account with a client ID and client secret. Suitable for team bots and automations that run without a user session. The secret is shown exactly once, immediately after creation. It cannot be retrieved afterwards.

Per-user connection lifetime: a connection lasts up to 30 days without use, and every use extends it. Only after that do you need to reconnect once.

For Claude, Cursor, VS Code, or Hermes, open «Connect apps», choose the app, and use the MCP URL, deep link, or ready-made snippet. On first connect, you sign in and, if asked, confirm the consent dialog; no external agent has to be created first. Only NHI agents (fixed machine identities) go through the agents area → «External agents» → «Connect agent», because that is where the client ID and secret are created. Then test the first call: «list_rooms()» returns your allowed rooms.

MCP-URL

https://<your-installation>/api/mcp

Within the remit

Check actions against room policies and decisions (validate_action); deliver curated, room-isolated knowledge (ask_brain); withhold answers containing personal data in rooms of the restricted data class before the agent sees them (DAT-03); immediate kill switch (a platform admin disables the agent, and access to ALL rooms is revoked); an evidence record for every question, every check, and every request. Isolation between rooms is enforced: an NHI agent sees only its home room, and a per-user agent sees exactly the rooms of the connected person. An agent can capture pending decisions as drafts in the room (propose_decision); the draft only becomes binding through human approval. It can also request time-limited exceptions (request_exception), read decisions in structured form (list_decisions, get_decision), and retrieve evidence (get_evidence). See the tool overview for details.

Outside the remit

NomOS governs access to knowledge, rules, and decisions. It does not run the agent and does not take over its compute environment. That separation is deliberate: it keeps the governance layer independent of any agent runtime, so it survives a change of tooling. At the Connected level, consultation is cooperative: the agent calls validate_action and ask_brain itself; what it never calls cannot be checked. Complete mediation is the Enforced level, a deliberate operating decision with its own preconditions rather than a switch. Some runtime checks, such as the secret scan, are wired as a capability in code and are not configurable through the policy interface.

The lifecycle of a connecting agent: orient → discover → read → check → contribute → trace. NomOS provides seventeen MCP tools for it:

  • list_rooms: shows the allowed rooms and a bounded topic digest from current governed decisions, so that the agent picks the right room first.
  • search_brain_catalog: searches visible Brain Store offers by text, room, origin, genre, or publisher; the search only reads and never changes room scope.
  • get_brain_offer: reads metadata, publisher, version, data class, content counts, and representative titles for a visible offer.
  • list_brain_relationships: shows direct, inherited, and available Brains for an allowed room with the exact next_action; it subscribes to or requests nothing.
  • request_brain_access: as the owner of the target room, requests access to a protected Corp Brain. A designated human publisher approver decides in the inbox; approval never creates a subscription.
  • ask_brain(room, question): asks a question with the full governance stack and returns an answer with citations, a run_id (evidence), and a conversation_id for follow-up questions. Without a reliable basis, the citation list is empty; what retrieval still found arrives separately as nearest_sources (context, not evidence).
  • list_decisions(room): reads the applicable decisions in a structured, deterministic way (no LLM), including inherited ones (marked as such); mine=true shows what became of the agent’s own proposals.
  • get_decision(room, key): reads a decision in full: content, status, owner, origin (for example, “proposed by agent X”), and associations.
  • get_decision_neighbours(room, key): a decision’s typed neighbours one step out, each with neighbour title and kind, relation type, direction, effect, edge status (active steers, proposed is inert), maintained flag, the room’s per-type weight, retrieval priority and provenance.
  • get_passage(room, knowledge_object_id, version?): reads a cited entry’s passage through the authorized reader: text, source document, version, validity, owner, and whether it is advisory knowledge or a binding decision. Same gates as the UI reader, current passage only, with version_served stated next to version_requested.
  • validate_action(room, action, content, tool?): pre-checks a planned action against the room constitution and returns allow, caution, require_approval, or block, plus an evidence ID. With tool, the room’s tool rules also feed into the verdict.
  • propose_decision(room, type, title, …): captures a decision arising in the dialogue as a draft (ADR, BDR, or SDR); only human approval makes it binding. Open drafts per proposer and room are capped (see the room details).
  • propose_knowledge(room, title, body_md, summary, source_note): submits knowledge produced during a task as a draft into the import review; it only enters the memory after a human accepts it.
  • list_knowledge_proposals(room): shows your own knowledge submissions across all statuses (draft, accepted, rejected); the feedback on propose_knowledge.
  • request_exception(room, policy_key, justification, scope?): requests a time-limited exception from a guardrail. Only a decision maker of the room (room owner, governance owner, or tenant admin) can approve it, in the inbox. Hard rules have no exception path.
  • get_evidence(run_id): opens the immutable evidence bundle of an answer (verdict, rules, citations, actor, time); input and output appear in the bundle only as hashes, never as plain text.
  • get_answer_relations(run_id): reads an answer’s structured governance relations: the depends_on prerequisites the block pulled in (with the decision that pulled them in) and the conflicts_with pairs, as data. Read-only, no language model, same scope as get_evidence.

The Brain Store tools only read; request_brain_access only submits a governed request. There are deliberately no tools that approve Corp access, subscribe to Brains, approve decisions, grant exceptions, manage rooms, or delete. Humans make the decisions, in the governed interface.

Agents area → choose a room → «Governance» view: the section «What a connecting agent receives» shows the global base harness, the effective room and client addendum, the tool list, and the capability matrix live from the server. All room members can read it; room owners edit the default and client-specific versions.

The global base harness stays identical everywhere and cannot be overridden. The default addendum applies to the room until Claude, Cursor, VS Code or Hermes gets its own fork. list_rooms and ask_brain additionally return the effective addendum source so an agent can see the difference.

Room owners can open an external agent’s detail to see the last attributable activity plus 7- and 30-day counts for governed requests, MCP resource reads and decision proposals. The projection is restricted to the selected room and the registered OAuth client.

The measurement is forward-only from release 0.40.1 and is not a lifetime total. Decision reads are deliberately absent until list_decisions and get_decision emit a complete deterministic read event; NomOS never invents this metric from other calls.

Modern MCP clients (for example, Claude) can register themselves with NomOS: paste the MCP URL into the client, and it signs itself up automatically. No ticket and no admin step are needed. The gate is your own consent: on first connect, a consent dialog appears, and only with your consent does the connection work.

The consent dialog shows which permissions the app requests: identity, profile, email, and, if the app asks for it, permanent access (the connection then persists without signing in again and is revocable at any time). The connection runs under your own identity: the app sees exactly what you are allowed to see, without extra privileges. If the app later asks for more, you are asked for consent again.

Nothing runs without consent. Until you consent on first connect, a self-registered app is listed as “Awaiting first consent” in the platform overview; only platform admins see this overview. There they see every self-registered connection (“Self-registered”) and can switch it off at any time through the kill switch. Every action still passes through the full governance stack: policies, personal data protection, and evidence.

To connect Claude, Cursor, VS Code, or Hermes, the «Connect apps» gallery gives each client the self-service path with the real endpoint, a deep link, or a ready-made snippet, without creating an agent first. Only for a machine identity (NHI) does the room owner create an agent under «External agents».

Open the gallery: Connect apps

Organizations don’t have to walk every member through the setup individually: if the client supports Team MCP (for example, Cursor, in the dashboard under «Integrations & MCP»), a team admin adds the NomOS server once, centrally. It is then available to all members, including automated Cloud Agents, without anyone having to enter the address themselves.

Access still stays governed per person: each member signs in individually on first connect and confirms their own consent dialog; identity stays per-user. A connection only ever sees what that member is allowed to see, and every connection appears separately under «My connections» and in the admins’ platform overview.

For per-user apps, Connect apps directly shows the MCP URL, deep link or ready-made snippet; the first call starts the OAuth flow with your consent. Only NHI agents first use the wizard to create a client ID and secret, which you then put into the agent configuration (for example «~/.hermes/config.yaml» for Hermes).

.mcp.json: Per-User (OAuth-Flow beim ersten Aufruf)

{
"mcpServers": {
"ainomos": {
"type": "http",
"url": "https://<your-installation>/api/mcp"
}
}
}

NHI, Schritt 1: Zugriffs-Token holen (client_credentials; das Secret wird getauscht, nicht als Bearer benutzt)

curl -s -X POST "https://<your-installation>/auth/realms/nimbus/protocol/openid-connect/token" \
-d grant_type=client_credentials -d client_id=<CLIENT_ID> -d client_secret=<CLIENT_SECRET>
# Antwort: { "access_token": "eyJ…" }. Dieses JWT im nächsten Schritt als Bearer einsetzen.
# Hinweis: das Token laeuft ab (Minuten) → bei Bedarf neu holen (Client mit Auto-Refresh).

.mcp.json für NHI, Schritt 2: das access_token als Bearer (Service-Account)

{
"mcpServers": {
"ainomos": {
"type": "http",
"url": "https://<your-installation>/api/mcp",
"headers": {
"Authorization": "Bearer <ACCESS_TOKEN>"
}
}
}
}
  • Support agent: a self-learning chatbot checks every response through validate_action against the team’s policies before replying. This way, no response leaves the agent unchecked.
  • Dev/coding agent: a coding agent validates proposed code changes against the team’s architecture decisions (ADRs) before opening a PR.
  • Research/analysis agent: an analysis agent must respect rules for personal data. In rooms of the restricted data class, NomOS withholds answers containing personal data before the agent sees them.
  • Ops automation (NHI): an unattended bot (for example, for night deployments) runs as NHI. The platform admin’s kill switch is the safety catch.

What is the difference between an internal and an external agent?

NomOS runs an internal agent; you configure its behavior, and every step goes through the full governance flow. You run an external agent; NomOS governs it cooperatively through MCP and keeps the kill switch ready.

When do I use which?

Want NomOS to operate the agent (hosted assistant with mission and budget) → internal. Already have your own agent and just want to govern it → external.

Does NomOS run my external agent?

No. An external agent runs outside; NomOS only responds to its MCP calls and governs them. The hard safeguard is the kill switch.

Where do I create each?

Both on the Agents page in the room: internal agent via «create» (mission/tools), external via «connect» (per-user/NHI). Internal agents require a 2–63-character identifier (lowercase letters, numbers, hyphens) and a positive budget. Field errors appear beside the input; server failures preserve your input. Retry a failed tool load before submitting. You can prepare a decision draft manually. This is neither an automatically detected approval gap nor an approval. Review the type, title, and basis before saving.

Where do I find the secret of a per-user agent?

There is none. Per-user agents are public clients with PKCE: proof comes from the person’s OAuth login. Only NHI agents have a secret (shown once at creation). The buttons in the detail view copy the client ID and the MCP configuration.

What is the difference between per-user and NHI?

Per-user: the agent acts with your identity (your rooms, your permissions). NHI: the agent has its own machine identity. It is not tied to a person and is suitable for team automations.

Where does the client secret come from, and what do I do if I lose it?

Keycloak generates the secret when you create an NHI agent. It is shown exactly once in the wizard; copy it immediately. If it is lost, there is no way to retrieve it. The only solution: remove the agent and create a new one.

What does the kill-switch do exactly?

A platform admin can disable an agent immediately. This deactivates the agent’s Keycloak client, and access to ALL rooms is revoked at once, regardless of how many rooms the agent had.

Can a disabled agent be re-enabled?

Yes. A platform admin can re-enable a disabled agent under Administration → «External agents» with «Re-enable»; this is recorded as evidence. A revoked agent stays disabled permanently.

Can the agent see data from other rooms?

Only from rooms that its identity belongs to. An NHI agent sees only its home room. A per-user agent sees exactly the rooms of the connected person. A call to a different room fails with a 403 error; the isolation is enforced in the backend.

Does NomOS run my agent?

No. NomOS provides an MCP interface, and your agent calls the tools. NomOS does not execute any of your agent’s code and does not control its compute environment.

What data does the agent receive?

ask_brain returns a governed answer with citations, owner, validity date, and an evidence ID, identical to the web UI. validate_action returns a verdict (allow, caution, require_approval, or block), the applicable binding rules, an AI assessment (marked as advisory), and an evidence ID.

How is PII handled?

NomOS checks responses for personal data with Presidio (DAT-03). In rooms of the restricted data class, ask_brain withholds an answer containing personal data before the agent sees it; in other rooms, it passes. validate_action marks personal data in a planned action as «caution». The platform admin configures the detection threshold.

Who can connect an agent?

Only the room owner can create or remove agents in the room. However, every member can connect their own apps under their own identity through «Connect apps». The platform admin sees all agents platform-wide and can disable any of them through the kill switch.