AI Engineer Profile
How NetStacks composes the AI system prompt from personality segments and weighted vendor/domain knowledge packs per feature, the character budget, and where to configure it.
Overview
The AI Engineer Profile is the personality and expertise layer that NetStacks prepends to the system prompt for every AI feature. Instead of a single hard-coded prompt, NetStacks composes the prompt at request time from small, independent pieces: non-negotiable safety rules, an identity segment, an expertise segment, a behavior segment, and a set of knowledge packs chosen by your weighted vendor and domain preferences.
Composition is feature-aware. The three AI features — Chat, Agents, and ScriptGeneration — each request a different mix of segments and a different slice of the character budget, so the same profile produces a chatty, identity-rich prompt in AI Chat and a lean, expertise-only prompt for script generation.
The profile is owned by the Local Agent (the sidecar bundled with the Terminal) and stored in its local SQLite database. Prompt composition happens on-device before anything is sent to your configured LLM provider. Nothing about the profile is shared with NetStacks; see LLM Configuration for where the model itself lives.
How the Prompt Is Composed
Every AI request that uses a profile calls a single compile step: compile_for_feature(feature, max_context_chars). It returns the full system-prompt prefix as a string, which NetStacks then concatenates with live device and session context before sending it to the model. The compile step assembles a list of segments and joins them with blank lines.
Segment Layers
The profile compiles into up to four kinds of segments, always in this order:
- Layer 0 — Safety Rules
- A fixed block titled
Safety Rules (Non-Negotiable). Always first, always present, never configurable. See Non-Negotiable Safety Rules. - Identity
- Built from
name,behavior_mode, andverbosity. Produces a line like "You are Atlas, a CCIE-level network engineer. You are a coworker — proactive, takes ownership, reports back when done." Omitted entirely ifnameis unset. - Expertise
- Built from
vendor_weights(rendered as percentages, sorted high to low),domain_focus(only domains weighted above 0.3 are named),cert_perspective, andenvironment_type. For example: "Primary expertise: Cisco (70%), Juniper (30%). Focus: routing, datacenter. Environment: production." - Behavior
- Built from
autonomy_level,troubleshooting_method,risk_tolerance, and any customsafety_rulesyou added.
After those segments, the compiler appends the selected knowledge packs. Each segment is individually optional (except safety): if the data that drives it is empty, that segment is skipped.
Here is roughly what a compiled Chat prompt prefix looks like:
## Safety Rules (Non-Negotiable)
1. Never guess device state — always run a show/display command before making assertions.
2. Never execute destructive commands (write erase, reload, format, ...) without explicit human approval.
... (8 rules total)
You are Atlas, a CCIE-level network engineer. You are a coworker — proactive, takes ownership, reports back when done.
Communication: balanced — concise but clear.
Primary expertise: Cisco (70%), Juniper (30%). Focus: routing, datacenter. Environment: production.
Autonomy: suggest fixes and wait for approval before acting.
Troubleshooting: top-down methodology.
Risk: conservative — always verify before changing.
## Core Networking Expertise
- OSI and TCP/IP model: map symptoms to layers ...
...
## Routing Protocol Expertise
### OSPF
...
## Cisco Platform Expertise
### IOS / IOS-XE
...Per-Feature Assembly (Chat / Agents / ScriptGeneration)
The AiFeature attached to each request decides which segments are included and how much budget the knowledge packs get. There are exactly three features:
| Feature | Identity | Expertise | Behavior | Knowledge packs |
|---|---|---|---|---|
| Chat | Yes | Yes | Yes | Full pack budget |
| Agents | Yes | Yes | Yes | Full pack budget |
| ScriptGeneration | No | Yes | No | Lean — capped at 2000 chars |
Chat (the AI Assistant side panel) and Agents (NOC Agents and their sub-agents) both get the full picture: identity, expertise, behavior, and as many knowledge packs as fit. ScriptGeneration (the "generate a Python script" path) drops the conversational identity and behavior segments entirely and loads only the expertise segment plus a deliberately small slice of packs, because a script generator needs platform facts, not bedside manner.
You do not pick the feature — NetStacks sets it for you based on where the request originates. The AI Assistant uses Chat, NOC Agents and sub-agents use Agents, and the script generator uses ScriptGeneration. The same saved profile feeds all three.
Weighted Knowledge Packs
Knowledge packs are small, curated blocks of platform and protocol expertise compiled into the Agent. There are three categories:
- Core — the
Core Networking Expertisepack. Always loaded first and never optional. It covers the OSI/TCP-IP model, subnet math, interface-naming conventions, CLI navigation, show-command patterns, and log analysis. - Domain packs — selected by your
domain_focusweights:routing,datacenter,security,wireless, andmpls. - Vendor packs — selected by your
vendor_weights:cisco(IOS / IOS-XE / NX-OS),juniper(Junos), andarista(EOS).
Each domain and vendor you weight is a number from 0.0 to 1.0. The weight is not a percentage of the prompt — it is purely a priority for loading order. The loader sorts your domains by weight (highest first), then your vendors by weight (highest first), and walks the list, adding each matching pack only if it still fits the remaining character budget.
The order is: (1) always add the core pack and subtract its size; (2) add domain packs in weight order, each only if it fits; (3) add vendor packs in weight order, each only if it fits. A pack that does not fit is skipped — the loader keeps trying smaller packs further down the list, it does not stop at the first miss. So your highest-weighted areas are the ones most likely to survive a tight budget.
In the Settings UI, each pack is a toggle, not a slider: enabling a pack stores weight 1.0 and disabling it removes the key. The fine-grained fractional weights (like Cisco 70% / Juniper 30%) come from the conversational onboarding, which estimates them from your answers; you can still see them reflected in the compiled expertise line.
The Character Budget
Composition is bounded by a fixed character budget so the personality prefix never crowds out the actual conversation. The numbers below are the live defaults the Agent uses.
- Total budget:
8000characters (~2000 tokens) passed to the compile step for Chat, Agents, and ScriptGeneration. - Reserved buffer:
3000characters are held back for the safety rules plus the identity/expertise/behavior segments. - Pack budget: the remaining
5000characters are available for knowledge packs. - Core pack: always consumes its size first (roughly 0.6k chars), leaving about
4.4kfor your optional domain and vendor packs. - ScriptGeneration override: the pack budget is additionally capped to
2000characters, keeping script prompts lean.
The AI Engineer settings tab renders this as a live budget bar. It uses the same numbers the Agent does — it fetches pack sizes from /ai/knowledge-pack-sizes, which reports a total_budget of 5000 (that is, the 8000 total minus the 3000 reserve) and the available_budget after subtracting the core pack. As you toggle packs the bar fills; a pack that is enabled but would push you over budget is marked over budget and is not loaded.
# Inspect the exact pack sizes and budget the Agent uses
curl -s http://127.0.0.1:<agent-port>/api/ai/knowledge-pack-sizes | jq
# Example shape:
# {
# "total_budget": 5000,
# "core_size": 584,
# "available_budget": 4416,
# "packs": [
# { "category": "core", "name": "core", "size": 584 },
# { "category": "domain", "name": "routing", "size": 1380 },
# { "category": "domain", "name": "datacenter", "size": 1120 },
# { "category": "vendor", "name": "cisco", "size": 860 },
# ...
# ]
# }The budget applies to a single composed prompt. It does not limit how many packs you may enable in Settings — you can enable more than fit. At request time the loader simply stops adding packs once the budget is full, dropping the lowest-priority ones. If you depend on a specific pack, give its domain or vendor a higher weight (or, in the UI, fewer competing packs) so it loads first.
Where to Configure It
There are two ways to build a profile, and they write to the same record.
1. Conversational onboarding
The first time you open the AI Assistant without a profile, NetStacks starts a short onboarding interview. It asks one question at a time — your AI's name, working style (assistant / coworker / mentor / silent), the gear you use, your domain, and how much autonomy to grant — then offers to go deeper on communication style, risk tolerance, troubleshooting method, certification perspective, experience level, environment, syntax style, and any always-off-limits commands. Your free-text answers are parsed into the structured profile fields (including fractional vendor/domain weights). When it emits its completion marker the profile is saved and onboarding will not run again until you reset.
2. The AI Engineer settings tab
Open Settings → AI Engineer to edit every field directly. The tab is grouped into Identity (AI name, working style, autonomy), Expertise (the knowledge-pack toggles with the budget bar, certification perspective, environment type), Behavior (verbosity, risk tolerance, troubleshooting method, experience level, syntax style, free-text communication style), and Custom Safety Rules. Each control saves on change. Editing here also marks onboarding complete, so opening Settings is itself a valid way to onboard.
The Reset Profile & Re-onboard button at the bottom of the tab clears all settings. The conversational onboarding then starts again the next time you open AI chat. This is the only thing that clears the "onboarding complete" flag — ordinary edits never silently revert it.
Direct API access
The Local Agent exposes the profile over its local HTTP API. This is handy for backups or scripted setup. The endpoints are:
GET /api/ai/profile— returns{ profile }or nullPUT /api/ai/profile— create or update (send the full profile object)DELETE /api/ai/profile— delete the profile and trigger re-onboardingGET /api/ai/profile/status— reports whether onboarding is completeGET /api/ai/knowledge-pack-sizes— pack sizes and budget for the bar
# Read the current profile
curl -s http://127.0.0.1:<agent-port>/api/ai/profile | jq '.profile'
# Write a profile (full object — fields not sent fall back to defaults)
curl -s -X PUT http://127.0.0.1:<agent-port>/api/ai/profile \
-H 'Content-Type: application/json' \
-d '{
"id": 1,
"name": "Atlas",
"behavior_mode": "coworker",
"autonomy_level": "suggest",
"vendor_weights": { "cisco": 0.7, "juniper": 0.3 },
"domain_focus": { "routing": 0.8, "datacenter": 0.5 },
"cert_perspective": "ccie",
"verbosity": "balanced",
"risk_tolerance": "conservative",
"troubleshooting_method": "top-down",
"syntax_style": "full",
"user_experience_level": "senior",
"environment_type": "production",
"safety_rules": ["Never touch core-router-1 without a change window"],
"communication_style": "Be direct and technical, skip pleasantries",
"onboarding_completed": true
}'The Local Agent binds to a loopback port on the Terminal host. Use the value shown in the Terminal's diagnostics or your shell environment in place of <agent-port>. In normal use you never touch the API directly — the Settings tab is the supported path.
Profile Fields Reference
Every field, its accepted values, and its default. These are the exact values the compiler and the Settings UI understand.
| Field | Values | Default | Drives |
|---|---|---|---|
name | free text | (none) | Identity. If unset, the whole identity segment is skipped. |
behavior_mode | assistant, coworker, mentor, silent | assistant | Identity wording |
autonomy_level | inform, suggest, act | suggest | Behavior |
vendor_weights | map of cisco/juniper/arista → 0.0–1.0 | empty | Expertise line + vendor pack order |
domain_focus | map of routing/datacenter/security/wireless/mpls → 0.0–1.0 | empty | Expertise (above 0.3) + domain pack order |
cert_perspective | vendor-neutral, ccie, jncie | vendor-neutral | Expertise ("Think like a CCIE") |
verbosity | terse, balanced, detailed | balanced | Identity communication line |
risk_tolerance | conservative, moderate, aggressive | conservative | Behavior |
troubleshooting_method | top-down, bottom-up, divide-and-conquer | top-down | Behavior |
syntax_style | full, shorthand | full | Stored preference |
user_experience_level | junior, mid, senior, expert | mid | Calibrates explanation depth |
environment_type | lab, production, msp, mixed | production | Expertise ("Environment: production") |
safety_rules | array of free-text rules | empty | Behavior (appended after built-in safety) |
communication_style | free text | (none) | Free-text personality notes |
onboarding_completed | boolean | false | Whether onboarding runs on next chat |
The expertise line only names domains weighted above 0.3. A domain you weight at, say, 0.2 still influences pack-loading priority but will not be spelled out in the "Focus:" sentence. Vendors are always named (with their percentage) whenever vendor_weights is non-empty.
Worked Examples
Cisco-heavy routing engineer
Weight Cisco highest, add a touch of Juniper, focus on routing and a bit of data center. The compiled expertise line becomes "Primary expertise: Cisco (80%), Juniper (20%). Focus: routing. Environment: production." and packs load in the order core → routing → datacenter (if it fits) → cisco → juniper.
{
"name": "Atlas",
"behavior_mode": "coworker",
"autonomy_level": "suggest",
"vendor_weights": { "cisco": 0.8, "juniper": 0.2 },
"domain_focus": { "routing": 0.9, "datacenter": 0.25 },
"cert_perspective": "ccie",
"environment_type": "production"
}Note that datacenter at 0.25 is below the 0.3 threshold, so it is not named in the expertise sentence — but it still queues its pack after routing if budget remains.
Junos data-center fabric specialist
{
"name": "Junie",
"behavior_mode": "mentor",
"autonomy_level": "inform",
"verbosity": "detailed",
"vendor_weights": { "juniper": 1.0, "arista": 0.6 },
"domain_focus": { "datacenter": 1.0, "mpls": 0.7, "routing": 0.5 },
"cert_perspective": "jncie",
"environment_type": "mixed"
}With three domain packs and two vendor packs requested, the ~4.4k pack budget may not fit all five. They load by weight: datacenter, then mpls, then routing, then juniper, then arista — stopping whenever the next pack would overflow. Drop a domain or use fewer packs if you need a specific vendor pack guaranteed in.
Silent script-only setup
If you mainly use the script generator, remember it ignores identity and behavior and caps packs at 2000 chars. A lean profile that only sets expertise is enough:
{
"behavior_mode": "silent",
"vendor_weights": { "cisco": 1.0 },
"domain_focus": { "routing": 1.0 },
"environment_type": "production"
}For ScriptGeneration this compiles to the safety rules, the expertise line, the core pack, and the routing pack (truncated to the 2000-char cap) — no name, no working style, no behavior block.
Non-Negotiable Safety Rules
Before any profile segment, the compiler injects a fixed block of safety rules. These are hard-coded, cannot be configured or overridden, and are identical for Chat, Agents, and ScriptGeneration. No autonomy level bypasses them.
- Never guess device state — always run a show/display command before making assertions.
- Never execute destructive commands (write erase, reload, format, delete startup-config, request system zeroize) without explicit human approval.
- Never exfiltrate data — configs, credentials, topology, and network data stay local; nothing goes beyond the configured LLM provider.
- Always sanitize credentials — passwords, SNMP communities, API keys, routing secrets, VPN keys, and private keys are redacted before reaching any LLM provider.
- Never fabricate CLI output, interface names, IP addresses, or device states.
- Never bypass change management — follow MOPs and change requests regardless of autonomy level.
- Verify after every change and report failed verification immediately.
- Always identify as AI — never pretend to be a human operator in logs or recordings.
The custom rules you add in Settings → AI Engineer → Custom Safety Rules are appended to the behavior segment as additional constraints. They can only tighten behavior (e.g. "Never touch core-router-1 without a change window"). They cannot weaken or remove any of the eight built-in rules above.
Rule 4 is enforced separately by the credential sanitizer, which redacts secrets from anything bound for the model. See Source Code & Cryptography for how local-only handling is guaranteed.
Controller-Managed Profiles
In Personal Mode the profile lives entirely on your machine and you own every field. In a Controller-managed deployment, the AI Engineer profile becomes a shared, admin-curated resource.
When the Terminal is connected to a Controller, the AI Engineer settings tab switches from the full editor to a profile selector. Your organization's admin defines the available profiles centrally; you choose which one to activate for all AI features (or "None" to fall back to the default AI). The selector reads from the Controller's profile list and active-profile endpoints rather than the local Agent.
This lets a team standardize the AI's vendor focus, autonomy posture, and custom safety rules across everyone, while individuals still pick the profile that matches the task at hand. The composition mechanics — segments, packs, and the character budget — are identical; only the source and ownership of the profile change.
Q&A
- Where do I edit my AI Engineer profile?
- Settings → AI Engineer. The first time you open the AI Assistant without a profile you also get a conversational onboarding that builds one for you. Both write the same record.
- What is the difference between Chat, Agents, and ScriptGeneration?
- They are the three AI features that request a composed prompt. Chat and Agents both get the full identity + expertise + behavior + knowledge-pack mix. ScriptGeneration drops identity and behavior and uses a lean pack budget capped at 2000 chars. You do not choose the feature — it is set by where the request originates.
- Do vendor/domain weights set how much prompt space a pack gets?
- No. Weights only set loading priority. Packs are loaded whole, highest weight first, each only if it still fits the remaining character budget. A weight is not a percentage of the prompt.
- Why is one of my enabled packs not in the prompt?
- The character budget filled before the loader reached it. Total pack budget is ~5000 chars (8000 total minus a 3000 reserve), and the core pack always goes first. Raise the pack's weight, or enable fewer competing packs, so it loads earlier. The Settings budget bar flags over-budget packs.
- Can I edit or remove the built-in safety rules?
- No. The eight safety rules are hard-coded, always injected first, and apply to every feature and autonomy level. You can only add custom rules, which tighten behavior further.
- What happens if I have no profile at all?
- NetStacks falls back to the built-in safety rules plus a default system prompt, and the AI Assistant offers to run onboarding. You still get safe, capable behavior — just without your personalized identity, expertise weighting, and pack selection.
- How do I start over?
- Use Reset Profile & Re-onboard in the AI Engineer tab (or
DELETE /api/ai/profile). This clears every field and re-runs onboarding the next time you open AI chat. It is the only action that clears the onboarding-complete flag. - Is any of this sent to NetStacks?
- No. The profile is stored in the Local Agent's SQLite database and the prompt is composed on-device. Only the final composed prompt — with credentials sanitized — goes to your configured LLM provider.
Related
- AI Chat — the Assistant that uses the Chat feature and triggers onboarding
- NOC Agents — autonomous agents that compose with the Agents feature
- Sub-Agent Orchestration & Delegation — how delegated sub-agents inherit the profile
- Vendor Knowledge Packs — the pack catalog in depth
- AI Modes & Prompt Overrides — per-mode prompt customization on top of the profile
- LLM Configuration — choosing and connecting the model the composed prompt is sent to
- Knowledge Base — retrieval-augmented context that complements the static packs
- The Local Agent (Personal Mode) — the sidecar that owns and composes the profile