{"slug": "boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling", "title": "BoxAgnts Tool System (7) — Skill Templates, Agent Proxies, and Cron Scheduling", "summary": "BoxAgnts introduced three new capabilities for its agent system: Skill templates for knowledge reuse, Agent sub-agents for task decomposition, and Cron scheduling for automated execution. Skills are Markdown prompt templates that guide AI behavior for repetitive tasks, while sub-agents and cron jobs extend the system's ability to handle large-scale and scheduled operations.", "body_md": "BoxAgnts' tool system, from WASM sandbox instruction-level isolation to the Tool trait's unified abstraction to the Provider layer's multi-model adaptation, has supported the secure execution and invocation of individual tools. But a complete Agent system requires three additional capabilities: knowledge reuse (how to ensure consistency when the AI faces repetitive tasks), task decomposition (how to break through the context window limits of a single conversation), and automated execution (how to trigger tasks on a schedule). These three capabilities are provided by Skill templates, Agent sub-agents, and Cron scheduling, respectively.\n\nConsider this scenario: a user says \"review the Rust code in the `src/`\n\ndirectory.\" The AI needs to execute a sequence of operations — use `file-glob`\n\nto find all `.rs`\n\nfiles, use `file-read`\n\nto read each one, use `file-grep`\n\nto check for potential problems, and output results in a specific format. Each of these 4 steps can be completed with existing tools, but if the AI has to decide the process from scratch every time, the output format and quality will be inconsistent each time.\n\nSkill solves exactly this problem. A Skill is a Markdown-format prompt template stored in `extensions/skills/<name>/SKILL.md`\n\n. The AI calls the `skill-tool`\n\ntool, passing a skill name; the system returns the expanded prompt text, and the AI executes subsequent operations accordingly.\n\nTaking the `code-review`\n\nskill as an example, its YAML frontmatter defines the metadata:\n\n```\n---\nname: code-review\ndescription: Perform deep review of code changes and output a structured report\nwhen_to_use: Use when the user requests code review or quality assessment\ntools: read, bash, glob, grep\nargs:\n  - name: target\n    description: File or directory to review; leave empty to review git staged changes\n    required: false\n---\n```\n\nThe body contains specific work instructions, covering review dimensions (logical correctness, security, performance, maintainability), output format (Markdown tables), and constraints (read-only, no code modifications).\n\nThe Skill execution flow is:\n\n`when_to_use`\n\ncondition`skill-tool`\n\n, passing `skill=\"code-review\"`\n\nand `args=\"src/\"`\n\n(the user-specified target path)`SkillTool`\n\nreads `code-review/SKILL.md`\n\n, strips the YAML header, and replaces `$ARGUMENTS`\n\nin the body with `\"src/\"`\n\n`file-glob`\n\n, `file-read`\n\n, `file-grep`\n\n, etc., and outputs review results in table formatKey code:\n\n```\n// tools/src/skill/skill_tool.rs\nasync fn execute(&self, input: Value, ctx: &ToolContext) -> ToolResult {\n    let params: SkillInput = serde_json::from_value(input)?;\n\n    if params.skill == \"list\" {\n        return list_skills(&search_dirs(ctx)).await;\n    }\n\n    let (_path, raw) = find_and_read_skill(&params.skill, &search_dirs(ctx)).await?;\n    let content = strip_frontmatter(&raw);\n    let prompt = content.replace(\"$ARGUMENTS\", &params.args.unwrap_or_default());\n\n    ToolResult::success(prompt)\n}\n```\n\nThe core difference between Skill and Tool lies in the execution subject. Tool's execution subject is the BoxAgnts runtime — the system calls `tool.execute()`\n\n, gets the result, and returns it to the AI. Skill's execution subject is the AI itself — the system only replaces template variables and returns text; subsequent tool invocations are decided and executed autonomously by the AI. This means Skill not only defines \"what to do\" but also \"how to do it\" and \"what output format to use\" — it's a higher-level abstraction.\n\nA single AI conversation hits two ceilings when handling large-scale tasks: context window and attention decay.\n\nThe context window ceiling is straightforward — if your project has 100 Rust files totaling 50,000 lines of code, the conversation history of reviewing all files will fill a 200K token context within a few turns. Attention decay is a more subtle problem: LLMs show significantly degraded information retrieval for content in the middle of long contexts (the so-called \"lost in the middle\" problem); by the time it's processing the 10th file, information from the 1st file may already be ignored.\n\nBoxAgnts' Agent sub-agent mechanism targets both of these problems. `AgentTool`\n\nallows the main Agent to create sub-agents, decomposing complex tasks into independent subtasks:\n\n```\n// tools/src/agent/mod.rs\nstruct AgentInput {\n    description: String,         // subtask description\n    prompt: String,              // complete instructions for the subtask\n    tools: Option<Vec<String>>,  // tools available to the sub-agent (default: all minus AgentTool)\n    max_turns: Option<u32>,     // max turns, default 10\n    model: Option<String>,      // model override (sub-agent can use a different model)\n    run_in_background: bool,    // whether to execute asynchronously in the background\n}\n```\n\nSub-Agent execution modes are divided into synchronous and asynchronous:\n\n**Synchronous mode** (`run_in_background = false`\n\n): The main Agent blocks after invocation, waiting for the sub-agent to complete its task and return results. Suitable for scenarios where the main Agent needs subtask results to continue.\n\n**Asynchronous mode** (`run_in_background = true`\n\n): The main Agent immediately receives an `agent_id`\n\n; the sub-agent runs independently in the background. The main Agent can continue processing other tasks and later query results via `agent_id`\n\n. Suitable for scenarios with multiple independent subtasks to process in parallel.\n\nA practical example: a user asks to \"comprehensively review this project.\"\n\n```\nMain Agent:\n  │\n  ├── Create sub-Agent A: \"Review backend/src/ Rust code, focusing on logic and security\"\n  │     └── Sub-Agent A: Independent Query Loop, using file-read/file-grep/bash\n  │     └── Returns: Markdown table listing 15 issues (3 critical, 7 medium, 5 minor)\n  │\n  ├── Create sub-Agent B: \"Review frontend/src/ Vue components, focusing on performance and accessibility\"\n  │     └── Sub-Agent B: Independent Query Loop\n  │     └── Returns: Markdown table listing 8 issues\n  │\n  └── Aggregate results of A and B, output comprehensive report\n```\n\nEach sub-agent has an independent context window (no shared conversation history), so there's no cross-contamination. Multiple sub-agents can execute in parallel (asynchronous mode); total time depends on the slowest one.\n\n**Recursion safety** is an important constraint. Sub-agents' tool lists exclude `AgentTool`\n\nitself by default — preventing infinite recursion of creating sub-sub-agents. If multi-level delegation is genuinely needed (main Agent → sub-agent → sub-sub-agent), the AgentTool can be explicitly included in the sub-agent's `tools`\n\nlist.\n\nLong-running, multi-tool, multi-turn Agent conversations can produce massive message histories. Even if each tool invocation's result is small (e.g., `file-read`\n\nreturning the content of one function), after 50 rounds the total token count becomes large, squeezing the model's reasoning space.\n\nBoxAgnts' `AutoCompactState`\n\nhandles this problem. It monitors the total size of message history and accumulated tool results, automatically triggering compression when approaching the model's context limit:\n\n```\nDetected context pressure (total message tokens approaching 80% of context_window)\n  │\n  ▼\n1. Filter compressible messages\n   - Prioritize compressing old tool_result ContentBlocks (tool execution results)\n   - Preserve the most recent N rounds of conversation in full\n   - Preserve all user and assistant messages (don't compress conversations)\n  │\n  ▼\n2. Generate summaries\n   - Old tool_results are replaced with: \"[Earlier tool result from file-read: read src/main.rs, returned 42 lines of Rust code]\"\n  │\n  ▼\n3. Recalculate token count\n   - If still over the limit, expand the range of compressed rounds\n```\n\nThere's a specific configuration item `tool_result_budget`\n\nwith a default value of 50,000 characters. When the cumulative character count of all tool results exceeds this value, the earliest tool_result is truncated and replaced.\n\nThe trade-off of the compression strategy is: tool results may contain details the AI needs for subsequent decisions (e.g., reading a specific field from a configuration file), and summarization loses this information. But for typical usage patterns — where the most recent few rounds' tool results remain the most relevant — this trade-off is acceptable.\n\nThe final dimension of tool execution is time. Not all AI tasks are triggered by users in real time — scenarios like \"generate today's code quality report at 9 AM every morning\" or \"check server logs for anomalies every 6 hours\" require scheduled execution.\n\nBoxAgnts' Cron system is built on `tokio-cron-scheduler`\n\n:\n\n``` js\npub async fn schedule_job(state: AppState, job_cfg: JobConfig) {\n    let cron_job = Job::new_async(&job_cfg.cron, move |_uuid, _lock| {\n        // On trigger:\n        // 1. Create a new AI conversation session\n        // 2. Inject job_cfg.prompt as the user message\n        // 3. Execute the complete Agent loop (identical to user-triggered conversations)\n        // 4. Record JobLog { id, executed_at, success, message, error }\n    });\n    scheduler.add(cron_job).await;\n}\n```\n\nEach Job's configuration includes:\n\n```\n{\n  \"name\": \"Daily Code Quality Report\",\n  \"cron\": \"0 9 * * *\",\n  \"prompt\": \"Check code changes in the src/ directory and generate today's quality report\",\n  \"model\": \"claude-sonnet-4-5\",\n  \"timeout\": 300,\n  \"enabled\": true\n}\n```\n\nKey design points:\n\n**Timeout protection**: Each Job has an independent timeout setting. If the AI conversation doesn't complete within 5 minutes, the system cancels that execution and logs a timeout entry. This prevents a runaway Agent from consuming all resources.\n\n**Scheduler persistence**: Job configurations and recent execution logs are stored in SQLite. All Jobs are automatically reloaded after a service restart.\n\n**Execution independence**: Each Cron trigger creates an independent conversation session with no shared message history. This is consistent with the Agent sub-agent isolation model — context pollution doesn't exist in the Cron scenario.\n\nDifferent Agents may need different permission levels. BoxAgnts supports filtering by tool permission level:\n\n```\npub async fn filter_tools_for_agent(\n    tools: Arc<Vec<Arc<dyn Tool>>>,\n    access: &str,\n) -> Arc<Vec<Arc<dyn Tool>>> {\n    match access {\n        \"full\" => tools,\n        \"read-only\" => {\n            tools.iter()\n                .filter(|t| matches!(t.permission_level(), ReadOnly | None)\n                    || t.name() == \"ask-user-question\")\n                .collect()\n        }\n        _ => tools,\n    }\n}\n```\n\nThis enables creating \"read-only Agents\" — they can use read-only tools like `file-read`\n\n, `file-glob`\n\n, `file-grep`\n\n, `web-fetch`\n\n, but cannot use write or execute tools like `file-write`\n\n, `file-edit`\n\n, `bash`\n\n. For an Agent that only does code review, this restriction is natural.\n\nBoxAgnts' advanced orchestration layer consists of three mechanisms, each addressing a key gap in Agent systems:\n\n**Skill templates** solve the knowledge reuse problem. Best practices for \"how to do something\" are solidified as Markdown prompt templates; the AI calls `skill-tool`\n\nto get the expanded instructions, then autonomously executes subsequent operations. The core difference from Tool is the execution subject — Tools are executed by the system, Skills are executed by the AI following instructions.\n\n**Agent sub-agents** solve the context window and attention decay problem. The main Agent creates sub-agents to handle independent subtasks, each with its own context window, avoiding the \"lost in the middle\" effect in long conversations. Synchronous mode is used when results are needed; asynchronous mode is used for parallel processing. `AgentTool`\n\nis excluded by default to prevent infinite recursion.\n\n**Cron scheduling** solves the temporal automation problem. Each Job has independent timeout protection, SQLite persistence, and isolated conversation sessions. Even if one scheduled task goes rogue, it won't affect other tasks or the main conversation.\n\n`AutoCompactState`\n\n's context compression and `PermissionLevel`\n\n's permission filtering serve as infrastructure supporting these three mechanisms: the former automatically compresses old tool results when message history approaches token limits; the latter allows different Agents to have different tool permission levels.", "url": "https://wpnews.pro/news/boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling", "canonical_source": "https://dev.to/guyoung/boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling-1o3h", "published_at": "2026-06-14 08:31:51+00:00", "updated_at": "2026-06-14 08:59:00.141521+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "large-language-models"], "entities": ["BoxAgnts", "Skill", "Agent", "Cron"], "alternates": {"html": "https://wpnews.pro/news/boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling", "markdown": "https://wpnews.pro/news/boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling.md", "text": "https://wpnews.pro/news/boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling.txt", "jsonld": "https://wpnews.pro/news/boxagnts-tool-system-7-skill-templates-agent-proxies-and-cron-scheduling.jsonld"}}