| Filename | Latest commit message | Latest commit date |
|---|---|---|
Synced from monorepo Changes: - Shell: accept target response id on rewind execute - Shell: stamp response id on chat user message chunks - Worktree: optional rebuild and stale git registration cleanup in auto-GC - Worktree: kind-aware auto-GC TTLs and config knobs - Worktree: macOS process CWD scan and Unix PID liveness for GC guards - Worktree: automatic throttled GC on startup (Linux age-based; non-Linux dead-only) - Pager: add `[ui].combine_queued_prompts` to batch queued follow-ups - Shell: stop overwriting user skills - Tools: read markdown in `skills/` directories untruncated - `/usage` shows per-session token and dollar usage in the TUI - Security: prompt on environment-dumping `ps` variants - Security: always-safe `kubectl` no longer runs arbitrary kubeconfig credential plugins without permission - Tools: make scheduler deletion durable - Shell: add relocation storage primitives - Shell: give side model calls their own conversation ids - Fix five workflow-runtime bugs (budget, pause, cancel, reconnect) - Security: peel `env -S` / `--split-string` operands in the Bash permission gate (managed deny/ask) - Pager: expose doctor in the TUI - Security: block unauthorized RCE via abused safe commands - Pager idle watcher cue: "1 subagent still running" instead of "watching · 1 subagent" - Security: block `rg --pre` arbitrary code execution in auto-mode - Voice: diagnose silent-mic failures (macOS permission) and add doctor/terminal-setup Voice section - App builder deployer: `allow_forking` and `show_built_with_grok` - Pager: stop stacking duplicate "Worked for" markers on parked turns - Shell: support `max` as a distinct reasoning effort tier - Tools: serialize background `/loop` fires on the whole work unit - Shell: add working-directory relocation state primitives - Proto: `ClientToolResult` and `ChatConfig` client-side tools - Shell: model providers - Chat: select App Builder product on the Build path - Shell: attach author identity to feedback when the deployment opts in - Doctor: fix for SSH wrap setup - Workflow authoring skills: create-workflow and import-claude-workflow docs - Add read-only grok doctor - Sandbox: apply Landlock without a controlling TTY - Pager: recover image paste over grok wrap on headless remotes - Pager: make actions screen-mode aware - Shell: resume sessions when the working directory moves - Pager: centralize terminal diagnostics - Workspace: gate inline shell file access - Pager: centralize terminal probes - Pager: edit minimal prompts in an external editor - Pager: standardize backgrounding on Ctrl+B - Shell: recap rides the parent turn's prompt cache - Tools: add scheduler lifecycle version clock Source-Revision: 0f4d7c91b8b2b408333f6de1e8a76cb8eaa71899 |
||
| .. | ||
| scripts | ||
| src | ||
| templates | ||
| Cargo.toml | ||
| README.md | ||
xai-grok-agent
Agent builder, definition parsing, and system prompt assembly.
This crate extracts a first-class Agent type from xai-grok-shell.
An Agent bundles tools, system prompt, system-reminder policy,
compaction policy, and model configuration into a single, portable
object that any host can consume — whether that host is
xai-grok-shell, another in-process host, or a headless batch runner.
Quick Start
From a definition file
Agent definitions are Markdown files with YAML frontmatter, stored
in .grok/agents/ (project-level) or ~/.grok/agents/ (user-level).
use xai_grok_agent::{AgentDefinition, AgentBuilder};
use xai_grok_tools::notification::ToolNotificationHandle;
// 1. Parse the definition file
let def = AgentDefinition::from_file(".grok/agents/code-reviewer.md")?;
// 2. Build the agent
let agent = AgentBuilder::new(cwd, None, ToolNotificationHandle::noop())
.from_definition(def)
.build()
.await?;
// 3. Use it
println!("Agent: {}", agent.name());
println!("Prompt: {}", agent.system_prompt());
let tool_defs = agent.tool_definitions().await;
Programmatic (no file)
let agent = AgentBuilder::new(cwd, None, ToolNotificationHandle::noop())
.with_name("my-agent")
.with_description("A custom agent")
.with_tools(vec!["read_file".into(), "grep".into()])
.build()
.await?;
Discover all definitions
use xai_grok_agent::discovery;
// Find all .md files in .grok/agents/ directories
let definitions = discovery::discover(&cwd);
// Find a specific agent by name (checks built-ins, then user dirs)
let reviewer = discovery::by_name("code-reviewer");
// Find with project-level priority
let agent = discovery::by_name_in_cwd("my-agent", &cwd);
Agent Definition File Format
Agent definitions are Markdown files with YAML frontmatter:
---
name: my-agent
description: What this agent does
# ... additional config fields
---
System prompt body goes here...
The frontmatter (between --- delimiters) is YAML configuration.
The body (after the closing ---) is the system prompt content.
Minimal example (extends base template)
---
name: code-reviewer
description: Reviews code for quality and security
tools:
- read_file
- grep
- list_dir
permissionMode: plan
---
You are a senior code reviewer. Analyze code and provide
actionable feedback organized by severity.
With promptMode: extend (the default), the body is appended to the
base template which includes tool calling conventions, formatting
rules, and user info. The author only writes persona-specific content.
Full prompt override
---
name: custom-agent
description: Agent with full control over the system prompt
promptMode: full
tools:
- read_file
- search_replace
- run_terminal_cmd
---
You are a custom agent.
Use ${{ tools.read_file }} to read files.
Use ${{ tools.search_replace }} to edit files.
${%- if tools.run_terminal_cmd %}
Use ${{ tools.run_terminal_cmd }} for shell commands.
${%- endif %}
<user_info>
OS: ${{ os_name }}
Shell: ${{ shell_path }}
Working Directory: ${{ working_directory }}
Date: ${{ current_date }}
</user_info>
With promptMode: full, the body IS the complete system prompt,
rendered through MiniJinja with custom ${{ }}/${% %} delimiters
(to avoid collisions with literal {{ }} in prose).
With completion requirement (orchestrated mode)
---
name: orchestrator-worker
description: Worker agent that must signal completion before ending a turn
completionRequirement:
tool: complete_task
reminder: >
You stopped without calling `complete_task`.
Please continue and call it when done.
recovery:
maxRetries: 5
baseDelayMs: 5000
maxDelayMs: 60000
toolConfig:
wait_for_instruction:
retry:
maxRetries: 1440
baseDelayMs: 5000
maxDelayMs: 30000
---
You are a worker agent in an orchestrated multi-agent workflow.
You MUST call `complete_task` before ending your response.
Frontmatter Schema Reference
All frontmatter keys use camelCase.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string |
Yes | — | Unique agent ID (lowercase, hyphens) |
description |
string |
Yes | — | When/why to use this agent |
promptMode |
string |
No | "extend" |
"extend" or "full" |
tools |
string[] |
No | inherit all | Tool allowlist. Omit = all tools. [] = none |
disallowedTools |
string[] |
No | [] |
Denylist (takes priority over tools) |
permissionMode |
string |
No | "default" |
"default", "acceptEdits", "dontAsk", "plan" |
skills |
string[] |
No | [] |
Skill names to pre-load |
agentsMd |
bool |
No | true |
Discover and inject AGENTS.md files |
outputFormat |
string |
No | "default" |
"default" or "concise" |
bash |
object |
No | defaults | Bash tool config overrides |
bash.timeoutSecs |
float |
No | 120.0 |
Bash command timeout |
bash.outputByteLimit |
int |
No | 200000 |
Max output bytes |
bash.cmdPrefix |
string |
No | null |
Command prefix |
toolNameOverrides |
map<string,string> |
No | {} |
Canonical → model-facing name map |
paramNameOverrides |
map<string,map> |
No | {} |
Per-tool param name map |
completionRequirement |
object |
No | null |
Tool that must be called before turn ends |
completionRequirement.tool |
string |
Yes* | — | Canonical tool name |
completionRequirement.reminder |
string |
Yes* | — | Reminder text when not called |
completionRequirement.recovery |
object |
No | null |
Recovery policy for the harness |
toolConfig |
map<string,object> |
No | {} |
Per-tool execution config |
toolConfig.*.retry |
object |
No | null |
Retry config for a tool |
*Required only when completionRequirement is set.
Prompt Assembly
promptMode: extend promptMode: full
────────────────── ─────────────────
1. Base template (MiniJinja) 1. Markdown body (MiniJinja, ${{ }}/${% %})
(tool conventions, formatting, 2. AGENTS.md section (if agentsMd: true)
user_info, background tasks) 3. Skills section
2. Markdown body (appended raw)
3. AGENTS.md section (if agentsMd: true)
4. Skills section
Template Variables (full mode)
| Variable | Description |
|---|---|
${{ tools.read_file }} |
Resolved name for read_file (or empty if disabled) |
${{ tools.search_replace }} |
Resolved name for search_replace |
${{ tools.run_terminal_cmd }} |
Resolved name for run_terminal_cmd |
${{ tools.grep }} |
Resolved name for grep |
${{ tools.list_dir }} |
Resolved name for list_dir |
${{ tools.todo_write }} |
Resolved name for todo_write |
${{ tools.skill }} |
Resolved name for skill |
${{ tools.get_task_output }} |
Resolved name for get_task_output |
${{ tools.kill_task }} |
Resolved name for kill_task |
${{ tools.web_search }} |
Resolved name for web_search |
${{ os_name }} |
Operating system (e.g. "macos", "linux") |
${{ shell_path }} |
Shell path (e.g. "/bin/zsh") |
${{ working_directory }} |
Workspace path |
${{ current_date }} |
Current date in the user's local timezone (YYYY-MM-DD) |
Conditionals: ${%- if tools.todo_write %}...${%- endif %} — block
is omitted when the tool is disabled.
Discovery Rules
Agent definitions are discovered from multiple locations with priority:
- Project-level (highest priority):
.grok/agents/*.md— walk fromcwdup to the git repository root. Files found closer tocwdtake priority. - User-level:
~/.grok/agents/*.md - Compat paths (lowest priority): additional vendor agent directories under the user home (when enabled)
- Built-in:
default_grok_build(),browser_use()
Name-based dedup ensures the highest-priority definition wins. For
example, a project .grok/agents/code-reviewer.md shadows a
user-level definition with the same name.
Crate Relationships
┌──────────────────┐
│ xai-grok-agent │ ← This crate
│ (Agent, Builder, │
│ Definition) │
└────────┬─────────┘
│ depends on
▼
┌──────────────────┐
│ xai-grok-tools │
│ (ToolBridge, │
│ ToolRegistry, │
│ ToolState) │
└────────▲─────────┘
│ depends on
┌────────┴─────────┐
│ xai-grok-shell │ uses AgentBuilder to create
│ (session host) │ Agent during session setup
└──────────────────┘
xai-grok-tools: ProvidesToolBridge,ToolRegistry,ToolState,SystemReminderLayer, and tool implementations.xai-grok-agentdepends on it for tool setup.xai-grok-shell: The application shell. UsesAgentBuilderto construct anAgentduring session creation. The shell re-exports some modules fromxai-grok-agent(AGENTS.md discovery, skills discovery, base prompt rendering).
Built-in Agents
| Name | Prompt Mode | Description |
|---|---|---|
grok-build |
extend | Default agent for software engineering tasks |
browser-use |
full | Web browsing and interaction agent |
Error Handling
AgentBuilder::build() returns Result<Agent, AgentBuildError>:
| Error | When |
|---|---|
ParseError |
Bad YAML, missing ---, wrong types |
MissingField |
Required field (name/description) absent |
UnknownToolOverride |
toolNameOverrides references nonexistent tool |
IoError |
File read error during AGENTS.md/skills discovery |
MiniJinjaError |
Template rendering failure |
Unknown frontmatter fields are silently ignored for forward compatibility — definitions written for newer versions work on older ones.
Development
# Check
cargo check -p xai-grok-agent
# Test
cargo test -p xai-grok-agent
# Clippy
cargo clippy -p xai-grok-agent --fix --allow-dirty
# Format
cargo fmt --all