diff --git a/docs/api-reference/veryfront/agent.md b/docs/api-reference/veryfront/agent.md index 25b34e594d..94ff5614e7 100644 --- a/docs/api-reference/veryfront/agent.md +++ b/docs/api-reference/veryfront/agent.md @@ -498,7 +498,7 @@ Input delivered to a hosted agent-service detached execution callback. | `LOAD_SKILL_CONTINUE_SAME_TURN` | Loading a skill is not doing the work; the turn continues. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/skill/load-skill-policy.ts#L30) | | `LOAD_SKILL_CONTINUE_SAME_TURN_NOW` | Shared load skill continue same turn now value. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/agent/conversation/delegation-policy.ts#L27) | | `LOAD_SKILL_DELEGATION_THRESHOLD` | Shared load skill delegation threshold value. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/agent/conversation/delegation-policy.ts#L31) | -| `LOAD_SKILL_OVERRIDE_FORWARDING` | A skill's model/thinking/maxSteps only take effect if the caller forwards them. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/skill/load-skill-policy.ts#L41) | +| `LOAD_SKILL_OVERRIDE_FORWARDING` | A skill's model/thinking/maxSteps only take effect if the caller forwards them. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/skill/load-skill-policy.ts#L49) | | `LOAD_SKILL_ROOT_OWNERSHIP` | Shared load skill root ownership value. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/agent/conversation/delegation-policy.ts#L29) | | `MAX_RUNTIME_SKILL_PROMPT_ENTRIES` | Maximum value for runtime skill prompt entries. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/agent/runtime/skill-prompt.ts#L12) | | `NO_DELEGATION_NARRATION_UNLESS_ASKED` | Shared no delegation narration unless asked value. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/agent/conversation/delegation-policy.ts#L20) | diff --git a/src/skill/load-skill-policy.ts b/src/skill/load-skill-policy.ts index 58135bdc3c..b982c8ac9f 100644 --- a/src/skill/load-skill-policy.ts +++ b/src/skill/load-skill-policy.ts @@ -37,9 +37,17 @@ export const LOAD_SKILL_CONTINUE_SAME_TURN = "Continue the same turn after calli * those fields. `createLoadSkillTool` returns `{ skillId, instructions, * references, scripts }`, so telling a factory-built agent to forward returned * overrides would name fields its `load_skill` never produces. + * + * The `invoke_agent` condition is load-bearing, not incidental. Overrides are + * applied only to that tool (`applySkillDelegationOverridesToToolInput` returns + * its input unchanged for any other tool name), and scoped `agent_` + * delegates accept only `{ input }` (`AgentToolInput`), so they cannot carry + * model/thinking/maxSteps at all. Phrasing the clause conditionally keeps it + * accurate on runs where `invoke_agent` is absent, without needing a dynamic + * description. */ export const LOAD_SKILL_OVERRIDE_FORWARDING = - "Pass through any returned model, thinking, or maxSteps overrides to invoke_agent when delegating."; + "If invoke_agent is available, pass through any returned model, thinking, or maxSteps overrides when delegating to it."; /** * The behavioural contract every `load_skill` tool description must state, diff --git a/src/skill/tools.test.ts b/src/skill/tools.test.ts index 8760d21c90..9215d4346d 100644 --- a/src/skill/tools.test.ts +++ b/src/skill/tools.test.ts @@ -737,4 +737,21 @@ describe("load_skill orchestration contract", () => { false, ); }); + + it("states override forwarding conditionally, because it only works for invoke_agent", () => { + // Some runs expose only scoped delegate tools (`agent_`) and no + // `invoke_agent`. Naming `invoke_agent` unconditionally points at a tool + // that is absent; generalising to "the available delegation tool" is worse, + // because scoped delegates CANNOT carry overrides — `AgentToolInput` is + // `{ input: string }`, and applySkillDelegationOverridesToToolInput returns + // its input unchanged for any tool other than invoke_agent. + // + // So the clause must be conditional: a no-op when invoke_agent is absent, + // accurate when it is present. veryfront/veryfront-issue-inbox#411. + assertStringIncludes(LOAD_SKILL_OVERRIDE_FORWARDING, "If invoke_agent is available"); + assertEquals( + LOAD_SKILL_OVERRIDE_FORWARDING.includes("the available delegation tool"), + false, + ); + }); });