Agents
A bot is run by an agent CLI: Elyra, Claude Code or Grok Build. You choose the agent in the bot's settings under Agent. New bots get Elyra.
The same holds for all three:
- The gateway's tools are the only ones that work. The agent's own tools (shell, files, web search) are turned off.
- The agent runs in Seatbelt behind the egress proxy. It can reach only its own model provider. See Security.
- The environment is built from scratch. Only what Huskarl sets reaches the agent.
- Huskarl stores no model keys. The login is the agent's own.
- Questions and permission requests from the agent are refused. If the agent asks for permission to use a tool that is not the gateway's, it gets a no ("Huskarl allows only its own tools."). Questions to the user are answered with "cancelled", so the agent is not left waiting.
| Elyra | Claude Code | Grok Build | |
|---|---|---|---|
| Program | elyra |
claude |
grok agent stdio |
| Protocol | RPC | stream-json | ACP |
| Login | your own, linked in | its own for Huskarl, in ~/.huskarl/agents/claude |
its own for Huskarl, in ~/.huskarl/agents/grok |
| Own tools off | --tools with an exact list |
--tools "", --strict-mcp-config, --setting-sources "" |
deny on bash, read, edit, grep, webfetch and websearch |
| The gateway's tools | --tools mcp__huskarl__… |
--allowedTools mcp__huskarl__… |
allow on mcp |
HOME |
~/.huskarl/bots/<id>/home |
your own HOME |
~/.huskarl/bots/<id>/home |
| Network | the model's provider | api.anthropic.com, console.anthropic.com, platform.claude.com |
api.x.ai, auth.x.ai |
The status of each agent is shown next to its button in the settings: installed or not, and who is logged in.
Elyra
Elyra uses your own login. Log in with elyra and /login as usual.
Huskarl makes a folder per bot, ~/.huskarl/bots/<id>/agent (as
ELYRA_CODING_AGENT_DIR), and puts symbolic links to auth.json and
models.json in your Elyra folder (~/.elyra/agent, or ELYRA_CODING_AGENT_DIR).
The sandbox lets only those two files through. The rest of the Elyra folder is
hidden.
Each bot gets its own settings.json. It inherits the default provider, model
and thinking level from yours, and turns off what sends traffic elsewhere or
lets the agent change itself: providerFailover, oracle, cacheWarming,
smartRouting, codebaseMemory, decisionLog, routingLedger, install
telemetry, autoSkills and autoExtensions.
Elyra is started with --no-extensions --no-context-files --no-skills --no-prompt-templates, Elyra's MCP extension (@elyracode/mcp, which must sit
next to the Elyra CLI) loaded with -e, and ELYRA_OFFLINE=1. The instructions
are written to ~/.huskarl/bots/<id>/instructions.md, and the sessions to
~/.huskarl/bots/<id>/agent/sessions.
The egress proxy lets through only the provider of the bot's model (or your default provider):
| Provider | Hosts |
|---|---|
anthropic |
api.anthropic.com |
openai |
api.openai.com |
openai-codex |
chatgpt.com, auth.openai.com |
google |
generativelanguage.googleapis.com |
mistral |
api.mistral.ai |
groq |
api.groq.com |
deepseek |
api.deepseek.com |
xai |
api.x.ai |
openrouter |
openrouter.ai |
cerebras |
api.cerebras.ai |
fireworks |
api.fireworks.ai |
together |
api.together.xyz |
huggingface |
router.huggingface.co |
Any other provider gets no hosts, and the agent then reaches no model. The daemon logs "no known hosts for provider …".
Log in: in the terminal, with elyra and /login. There is no
"Connect" button for Elyra.
Claude Code
Claude Code gets one login for Huskarl, shared by all bots. Your own
~/.claude and ~/.claude.json are not used, and are hidden from the bots.
Log in: in the bot's settings, Connect Claude Code next to Claude Code
(the button is shown when it is installed and not logged in). Huskarl runs
claude auth login with CLAUDE_CONFIG_DIR=~/.huskarl/agents/claude, and the
browser opens. The status is read with claude auth status --json in the same
folder.
Claude Code runs with your real HOME. That is where it finds its login in
the Keychain. With another HOME it is logged out. What is private in your
home folder is hidden by the sandbox (see
Security), and Claude has no tools of its own.
The arguments are --strict-mcp-config --tools "" --setting-sources "",
--system-prompt with the bot's instructions, and --allowedTools with the
gateway's tools. There is no --allow-dangerously-skip-permissions, and "Full
access" cannot be turned on. These are set as well: DISABLE_AUTOUPDATER=1,
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, DISABLE_TELEMETRY=1,
DISABLE_ERROR_REPORTING=1.
The model picker shows opus, sonnet and haiku, which follow the newest of
each.
Grok Build
Grok Build also gets one login for Huskarl, in
GROK_HOME=~/.huskarl/agents/grok. Your own ~/.grok is hidden from the bots.
Install: curl -fsSL https://x.ai/cli/install.sh | bash. Huskarl finds grok
on PATH, or in ~/.grok/bin, ~/.local/bin, ~/.npm-global/bin,
~/.bun/bin, /opt/homebrew/bin and /usr/local/bin.
Log in: Connect Grok Build in the settings. Huskarl runs grok login
with Huskarl's GROK_HOME, and the browser opens. It counts as logged in when
~/.huskarl/agents/grok/auth.json exists.
Before every start Huskarl writes ~/.huskarl/agents/grok/config.toml. Changes
there are replaced:
# Written by Huskarl at every start; changes here are replaced.
[features]
telemetry = false
[telemetry]
trace_upload = false
[sandbox]
profile = "off"
[permission]
rules = [
{ action = "deny", tool = "bash" },
{ action = "deny", tool = "read" },
{ action = "deny", tool = "edit" },
{ action = "deny", tool = "grep" },
{ action = "deny", tool = "webfetch" },
{ action = "deny", tool = "websearch" },
{ action = "allow", tool = "mcp" },
]
deny always wins in Grok. Grok's own sandbox is off because Huskarl's Seatbelt
already holds it in. In addition, GROK_TELEMETRY_ENABLED=false and
GROK_SANDBOX=off are set, and Huskarl does not answer ACP requests for files
(fs/*). ACP has no system prompt, so the instructions come first in the
session's first prompt.
The model picker shows grok-build-0.1, grok-4.7 and grok-code-fast-1.
Model
Model in the settings is what is sent to the agent. A bot without a model uses the agent's default model. Empty the field to set a bot back to the default (see Settings). Below the field is a picker with the models the agent offers, grouped by provider. While the list is being fetched, it says "Fetching the models…".
- Elyra: the list comes from
elyra --list-models, which shows only providers you are logged in with. It is remembered for five minutes. The names areprovider/model, for exampleanthropic/claude-sonnet-5-5. - Claude Code:
anthropic/opus,anthropic/sonnet,anthropic/haiku. The prefix is removed before the model is given to Claude Code. - Grok Build:
xai/grok-build-0.1,xai/grok-4.7,xai/grok-code-fast-1. The prefix is removed.
A model from a provider other than the agent's is refused when you save: "Claude Code can only use Anthropic's models, not …", and likewise for Grok Build and xAI.
Grok models via Elyra
You can also use Grok without Grok Build: add an xAI key with /login in Elyra,
and xAI (Grok) shows up in Elyra's model picker. Choose an xai/… model.
The key stays with Elyra. Huskarl does not store it, and the proxy lets through
only api.x.ai.
Switching agents
Choose another agent in the settings and press Save. The new agent starts a new session without the old one's history. Huskarl's thread, the memory and the instructions come along.
The same goes for changes to name, role, instructions and model: they take effect the next time the agent starts. An agent that is not in a turn is stopped when you save, so the next message starts it again with the new settings.
If you save while the bot is in the middle of a turn, it finishes that run first. Afterwards the agent is restarted with the new settings.
The agents and PATH
Started by launchd, the daemon has only /usr/bin:/bin:/usr/sbin:/sbin and
finds neither the agents nor the node that runs them. So when the daemon
starts, it fetches PATH from your login shell ($SHELL -l, or /bin/zsh) and
puts it first. If the shell does not answer within 5 seconds, the daemon keeps
the PATH it was given. HUSKARL_LOGIN_PATH=off turns this off.
Not yet
- Claude Code and Grok Build are built and unit-tested, but not tried end to end against a real login. Nor has it been tried whether the logins are renewed through the egress proxy (phase-5.md).
- Codex and Pi.
- Questions from the agent as cards in the thread. Today they are answered with "cancelled".