Naming agents
When you first wire kilasec into a network, the Agents page is going to show a lot of unknown_agent (or per-IP placeholders like host-10.0.5.108). That's the system being honest: it captures the facts (source IP, MAC, user-agent, key fingerprint) but doesn't assign a name until the network tells it one.
This guide covers the three ways names get resolved and what to do when none of them works.
How names actually get assigned
In order of strength, kilasec uses the strongest signal it has:
- Verified identity token — the agent sends a token minted on Identity → Agent identity tokens (injected automatically by the
kilasec_agentpackage); the collector verifies it against the cloud. The only verified name in this list — everything below is inferred or self-declared. - DHCP-pushed identity — your DHCP server stamps
(name, team, vlan)onto the lease via a vendor option, and the collector reads it. Strongest possible attribution. - DHCP lease feed — a small daemon on your DHCP server POSTs
/var/lib/dhcp/dhcpd.leasestokilasec.com/api/v1/leasesevery minute. Cloud uses it to enrich audit rows. → Reference: DHCP leases. - Reverse DNS —
gethostbyaddr(source_ip)on the collector. Works whenever your DHCP server auto-populates PTR records, which is the default on most modern routers. - mDNS (Bonjour) — the collector listens on the LAN for
_workstation._tcp.local.announcements. Macs broadcast their hostname by default. Great for Mac-heavy networks even without DHCP integration. - Request headers —
x-agentfw-agent: my_botfrom an SDK or wrapper that opted in. AGENTFW_AGENTenv var — set by the agent process itself; default falls back tounknown_agent.- Manual override — the admin types a name in the Agents page. Persisted server-side and applied at display time.
What the Agents page shows
Each card on Agents clusters by the strongest stable identifier it has:
- If the addon resolved a real name from DHCP / reverse-DNS / mDNS, the cluster is keyed on that name.
- Otherwise, the cluster is keyed on the source IP. One card per host — not "everything in one big
unknown_agentbucket." - Manual overrides win over all of the above.
Provenance is always visible:
A named card shows you why it's named the way it is — the audit trail of signals (from reverse_dns: mwilson-mbp, User-Agent: claude-cli/0.7, etc.). An unnamed card shows the suggested names clickably: one click adopts a signal as the manual name.
Fixing the "everything is unknown_agent" problem
Walk down the list, in order:
Step 1 — reverse DNS
This is the cheapest win. On the collector, run:
dig -x 10.0.3.42 +short # the source IP from one of your unnamed rowsIf it returns nothing, your DHCP server isn't writing PTR records. Either:
- Fix that at the DHCP level (most routers have a "Register DNS" or "DDNS" toggle), or
- Install the DHCP lease feeder so kilasec can resolve from the lease file directly.
Step 2 — mDNS
On a Mac LAN, this usually Just Works. On Linux/container hosts, the collector container needs --network host (or multicast routing enabled) for mDNS to function.
# In your collector environment, this should yield names:
avahi-browse -arpt _workstation._tcp 2>/dev/null | headStep 3 — in-agent identity (the reliable fix for Python agents)
For any Python agent, the kilasec_agent package (in the agents bundle, kilasec-agents/pyagent/) tags every outbound request — no per-request code:
pip install /path/to/kilasec-agents/pyagent
KILASEC_AGENT=billing-reconciler python3 agent.pyor with zero code changes at all, from the deployment side:
PYTHONPATH=/opt/kilasec-agents/pyagent KILASEC_AGENT=billing-reconciler python3 agent.pyAdd KILASEC_AGENT_TOKEN=kat_… (minted on Identity → Agent identity tokens) to make the name verified instead of self-declared — see In-agent identity. For non-Python agents, send x-agentfw-agent: <name> on every request (most HTTP clients support default headers).
Step 4 — manual
For the residual cases — usually appliances, IoT, or hosts that simply don't have a name — click the Edit button on the card and assign one. The override is stored server-side (cloud /v1/identities table), tenant-scoped, and applied to all historic and future rows for that source.
Renames apply retroactively
This is important and surprising the first time you see it: when you rename host-10.0.3.42 to mwilson-mbp, every audit row that has source_ip 10.0.3.42 now displays as mwilson-mbp — including last week's.
That's because audit rows store the raw facts (ip, mac, hostname at time of event) and the UI joins on the current identities table at query time. So you can rename without re-writing history.
A snapshot of the name at the time of the event is also stamped onto the row for forensics; the join just hides it unless you ask for it.
When you really don't have a name
Sometimes the network doesn't know. A laptop on the guest VLAN, a container with no hostname, a vendor appliance. The Agents page handles these:
- The card shows
host-10.0.5.108instead ofunknown_agent— the IP still identifies the source. - If the same source has consistent user-agent ("OpenAI-Python/1.0"), that's offered as a suggested name.
- Suggestions are non-destructive: clicking one just sets the display name. The underlying audit rows are unchanged.
→ See also: Concepts: Identity model.