Skip to content

feat(delegation): add named subagent capability profiles - #4929

Closed
malaiwah wants to merge 2 commits into
NousResearch:mainfrom
malaiwah:codex/delegation-profiles
Closed

feat(delegation): add named subagent capability profiles#4929
malaiwah wants to merge 2 commits into
NousResearch:mainfrom
malaiwah:codex/delegation-profiles

Conversation

@malaiwah

@malaiwah malaiwah commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds named delegation capability profiles for delegate_task.

This lets subagents inherit a policy bundle instead of only a raw toolset list. A profile can define child-safe toolsets, memory access mode, memory-provider tool exposure, and terminal backend overrides.

It also hardens child tool scoping to work on resolved tools instead of exact toolset-name intersection, which fixes dynamic/alias-style toolsets like MCP servers and avoids leaking blocked tools through umbrella toolsets.

Related Issue

Fixes #4928

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • add built-in delegation profiles: restricted, friendly, privileged
  • add delegation.default_profile and delegation.profiles config keys
  • add delegate_task(profile=...) and per-task profile support in the schema
  • scope child tools by resolved tools, not exact toolset-name intersection
  • add child memory policy controls: none, read, write
  • allow profile-driven terminal overrides, including backend selection
  • reuse per-task terminal overrides in file sandbox creation too
  • update docs and cli-config.yaml.example
  • add focused tests for profile resolution, child agent construction, tool scoping, and backend override behavior

How to Test

  1. Set delegation.default_profile: friendly in ~/.hermes/config.yaml.
  2. Run a task that delegates and confirm the child gets terminal/file/web plus read-only memory context.
  3. Run python -m pytest tests/tools/test_delegate.py tests/tools/test_delegate_toolset_scope.py tests/tools/test_parse_env_var.py -q.

Validation on this branch:

  • targeted profile/delegation slice: 68 passed
  • full suite: 7883 passed, 172 skipped, 1 xfailed, 7 failed
  • the 7 failures were outside the touched files in this PR

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

@malaiwah

malaiwah commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

Validation on this branch:

  • targeted profile/delegation slice: 68 passed
  • full suite: 7883 passed, 172 skipped, 1 xfailed, 7 failed
  • the 7 failures were outside this PR's touched files

@malaiwah

malaiwah commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

Added a small follow-up test commit on this branch.

New coverage:

  • top-level and per-task profile propagation in delegate_task
  • runtime gating for built-in memory writes when memory_write_enabled=false
  • runtime gating for provider memory tools when provider_tool_access=false
  • provider memory tool dispatch still works when access is enabled

Validation:

  • python -m pytest tests/tools/test_delegate.py tests/tools/test_delegate_toolset_scope.py tests/tools/test_parse_env_var.py tests/test_run_agent.py -q
  • 294 passed

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/delegate Subagent delegation labels May 1, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused tests and documentation. Current main has since established a stricter delegation boundary that this implementation crosses.

Problems

  • tools/delegate_tool.py:1010 makes profile model-facing, while the profile controls toolsets, memory access, and terminal backend overrides. The same PR also restores model-facing toolsets at tools/delegate_tool.py:999.
  • Current main intentionally prevents this: delegated children receive toolsets=None at tools/delegate_tool.py:2492, and tests/tools/test_delegate.py:74 asserts that neither top-level nor per-task toolsets is exposed to the model. This was implemented by ba0bc01d1f740c562b55925e404b82a48809c364 specifically because capability selection must not be model-controlled.

Suggested changes

  • Do not expose a profile selector that changes child capabilities through delegate_task; preserve parent-toolset inheritance.
  • Any reusable policy work would need to be re-scoped as operator-controlled configuration and rebuilt against the current dispatch path.

This is an automated hermes-sweeper review.

Comment thread tools/delegate_tool.py
"full-stack tasks."
),
},
"profile": {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a capability bundle model-selectable: the profile controls child toolsets, memory access, and terminal backend overrides. Current main intentionally removed model-facing child toolset selection (ba0bc01d1f740c562b55925e404b82a48809c364); please do not reintroduce capability selection through this schema.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
@teknium1 teknium1 added the area/profiles Multi-profile isolation, HERMES_HOME scoping label Jul 19, 2026
@malaiwah

malaiwah commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing this PR — the core architectural objection is fundamental, and the design direction for delegation profiles is still unresolved among the maintainers.

Why close:

teknium1's review (Jul 12) identifies the central issue: this PR reintroduces model-facing capability selection in delegate_task's schema (profile at line 1010, toolsets at line 999). Main deliberately removed this in commit ba0bc01d1f — capability selection must not be model-controlled. Delegated children now receive toolsets=None (line 2492), and tests/tools/test_delegate.py:74 explicitly asserts that toolsets is not exposed to the model.

The suggested path forward — "re-scoped as operator-controlled configuration and rebuilt against the current dispatch path" — is a ground-up rework, not a cherry-pick.

Competing approaches still unresolved:

With four PRs from different contributors all targeting the same problem and none merged, it's clear the maintainers want to settle the design direction before accepting any implementation. Re-opening a salvaged version of this PR would add a 5th entry to an unresolved design conversation rather than move it forward.

What's salvageable for a future attempt:

  • The operator-controlled config schema (delegation.profiles, delegation.default_profile) — not model-facing
  • The child tool scoping hardening (resolved tools vs exact-name intersection, fixes MCP/alias leakage)
  • The memory policy controls (memory_write_enabled, provider_tool_access)

These components could inform whatever approach the maintainers eventually settle on.

Thanks @teknium1 for the review. Issue #4928 stays open.

@malaiwah malaiwah closed this Aug 8, 2026
@malaiwah
malaiwah deleted the codex/delegation-profiles branch August 8, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/delegate Subagent delegation type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: add named delegation capability profiles for subagents

3 participants