mirror of
https://github.com/JackChen-me/open-multi-agent.git
synced 2026-10-19 01:29:57 -05:00
feat(core): add hybrid semantic execution routing
This commit is contained in:
1 parent
136d8ed56e
commit
f373b638cf
24 files changed
+2150
-71
No files matched your search
+114
-9
@@ -8,12 +8,68 @@ Execution Routing decides the execution topology for an automatic `runTeam()` ca
|
||||
|
||||
1. Explicit `mode: 'single' | 'team'`.
|
||||
2. Declared governance topology or `preferredUnderBudget` degradation policy.
|
||||
3. The per-run `executionRouter`.
|
||||
4. The orchestrator-level `executionRouter`.
|
||||
5. The built-in `DeterministicRouter`.
|
||||
3. The per-run or orchestrator-level custom `executionRouter`.
|
||||
4. The built-in `DeterministicRouter`.
|
||||
5. When the default/fallback deterministic result is Single, the semantic
|
||||
`TaskProfiler` and deterministic semantic policy.
|
||||
|
||||
Routers run only for automatic, non-`planOnly` topology selection. They never override an explicit mode, declared role topology, or governance budget policy. `governanceIntent: 'none'` retains automatic topology selection, while still counting as an explicit governance declaration for consequential-tool confirmation.
|
||||
|
||||
A valid custom Router decision is final and is never reinterpreted by the
|
||||
Profiler. If a custom Router fails and its deterministic fallback selects
|
||||
Single, Hybrid routing may profile that fallback candidate.
|
||||
|
||||
## Hybrid semantic routing
|
||||
|
||||
Hybrid is the default strategy. It preserves the cheap deterministic Team
|
||||
decision and adds at most one no-tool model call only when that router would
|
||||
otherwise choose Single:
|
||||
|
||||
```ts
|
||||
const orchestrator = new OpenMultiAgent({
|
||||
executionRouting: {
|
||||
strategy: 'hybrid',
|
||||
confidenceThreshold: 0.7,
|
||||
failurePolicy: 'fallback',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
`LLMTaskProfiler` produces a strict, provider-neutral `TaskProfile` containing
|
||||
only inferred semantic signals: independent evidence sources, independent
|
||||
review, conflicting objectives, side-effect intent, permission isolation,
|
||||
decomposability, parallelism, complexity, confidence, and bounded reasons. The
|
||||
goal is treated as untrusted data. The Profiler receives no Agent/Coordinator
|
||||
system prompts, credentials, tool implementations, or complete permission
|
||||
details and cannot call tools.
|
||||
|
||||
The model does not choose the topology. A deterministic policy consumes the
|
||||
profile together with framework-computed facts:
|
||||
|
||||
- high-confidence independent evidence, review, conflict, or genuinely
|
||||
parallel work may upgrade Single to Team;
|
||||
- inferred side-effect/isolation needs that intersect with consequential
|
||||
effective grants or multiple caller-declared `permissionBoundary` values
|
||||
produce `ROUTING_DECLARATION_REQUIRED`;
|
||||
- low confidence or no material signal keeps Single;
|
||||
- V1 never changes Team to Single.
|
||||
|
||||
`ROUTING_DECLARATION_REQUIRED` is raised before any Coordinator, worker, or
|
||||
tool-capable Agent starts. A profile never creates `requiredRoles`, approves a
|
||||
side effect, or proves that governance was satisfied.
|
||||
|
||||
The built-in Profiler resolves its adapter in this order:
|
||||
|
||||
1. per-run `executionRouting.adapter`;
|
||||
2. orchestrator `executionRouting.adapter`;
|
||||
3. the effective Coordinator adapter;
|
||||
4. an adapter created from the orchestrator's default provider/model.
|
||||
|
||||
`executionRouting.model` follows the same per-run-over-orchestrator precedence,
|
||||
then the Coordinator model and default model. Profiler usage is charged to the
|
||||
run token/cost budget and appears in routing tracing and
|
||||
`TeamRunResult.totalTokenUsage`.
|
||||
|
||||
## Contract
|
||||
|
||||
```ts
|
||||
@@ -55,7 +111,15 @@ The per-run router wins over the orchestrator router. A decision is valid only w
|
||||
|
||||
## Failure behavior
|
||||
|
||||
Routing is advisory infrastructure and must not turn into a run failure. If a custom router throws, rejects, or returns an invalid decision, OMA falls back to `DeterministicRouter`. The returned decision uses the built-in router version and appends a fallback reason to `reasons`.
|
||||
The default `failurePolicy: 'fallback'` keeps routing infrastructure advisory.
|
||||
If a custom Router throws, rejects, times out, or returns an invalid decision,
|
||||
OMA falls back to `DeterministicRouter`. Profiler timeout, refusal, throw, or
|
||||
invalid structured output keeps that deterministic route.
|
||||
|
||||
Set `failurePolicy: 'fail'` to terminate instead. Profiler failures use
|
||||
`ROUTING_PROFILER_FAILED`; Router/Profiler deadlines use `ROUTING_TIMEOUT`.
|
||||
Machine-readable `status`, `requestedRouterVersion`, and `fallbackCode` fields
|
||||
remove the need to parse human-readable `reasons`.
|
||||
|
||||
```ts
|
||||
result.routingDecision
|
||||
@@ -65,7 +129,10 @@ result.routingDecision
|
||||
// 'The goal has one concise action and no multi-stage structure.',
|
||||
// 'Execution router fallback: custom decision failed (Error).'
|
||||
// ],
|
||||
// routerVersion: 'deterministic-v1'
|
||||
// routerVersion: 'deterministic-v1',
|
||||
// status: 'fallback',
|
||||
// requestedRouterVersion: 'application-router-v1',
|
||||
// fallbackCode: 'router-error'
|
||||
// }
|
||||
```
|
||||
|
||||
@@ -76,6 +143,27 @@ actual `routerVersion`. See the
|
||||
[five routing trace source classifications](./observability.md#trace-spans),
|
||||
including the compatibility-only `legacy-deterministic` label.
|
||||
|
||||
When semantic profiling ran, `semanticRoutingAssessment` is attached both to
|
||||
the result and routing record. It reports the inferred profile/version,
|
||||
deterministic legacy decision, semantic recommendation, actual topology, usage,
|
||||
and structured fallback state. The executed task topology, final tool grants,
|
||||
and `ExecutionReceipt` remain governance truth.
|
||||
|
||||
## Deterministic compatibility mode
|
||||
|
||||
Use one line to restore the previous no-profiler behavior:
|
||||
|
||||
```ts
|
||||
const orchestrator = new OpenMultiAgent({
|
||||
executionRouting: { strategy: 'deterministic' },
|
||||
})
|
||||
```
|
||||
|
||||
This makes no extra model call and retains the existing deterministic Router
|
||||
result and custom-Router fallback behavior. The compatibility path remains
|
||||
available for offline use, incident degradation, and the entire major release
|
||||
cycle.
|
||||
|
||||
## Built-in deterministic policy
|
||||
|
||||
`DeterministicRouter` wraps the single `isSimpleGoal()` heuristic; OMA does not maintain a second competing heuristic.
|
||||
@@ -94,12 +182,29 @@ Language coverage is tiered honestly rather than claimed uniform:
|
||||
|
||||
CJK verb-connective sequencing is a deliberate non-goal. Chinese keeps a verb-connective pattern because its verbs are invariant tokens, but Japanese and Korean verbs inflect (Japanese て-form, Korean agglutinative endings), so matching them would require morphological analysis this heuristic intentionally avoids; explicit markers and enumeration cover the structural signal instead.
|
||||
|
||||
This policy is intentionally honest, cheap, and language-neutral rather than semantically ambitious. Semantically equivalent English, Chinese, Japanese, and Korean goals should select the same execution mode. Applications that need domain-specific semantics should inject an `ExecutionRouter` or declare an explicit mode/governance topology.
|
||||
This policy remains intentionally cheap rather than semantically ambitious.
|
||||
Hybrid routing corrects high-confidence false-Single cases after this step.
|
||||
Applications that need domain-specific, authoritative decisions should still
|
||||
inject an `ExecutionRouter` or declare an explicit mode/governance topology.
|
||||
|
||||
## Governance boundary
|
||||
|
||||
Execution Routing does not declare governance. The consequential-tool fallback still treats only `governanceIntent === undefined` as undeclared, regardless of which router selected Single or Team. Router decisions also cannot satisfy named-role or independent-review requirements; those facts continue to come from structured governance declarations and the executed topology.
|
||||
Execution Routing does not declare governance. The consequential-tool fallback
|
||||
still treats only `governanceIntent === undefined` as undeclared, regardless of
|
||||
which router selected Single or Team. Router decisions and TaskProfiles cannot
|
||||
satisfy named-role or independent-review requirements; those facts continue to
|
||||
come from structured governance declarations and the executed topology.
|
||||
|
||||
## Behavior change
|
||||
## Major-version migration
|
||||
|
||||
The built-in automatic route recognizes short CJK (Chinese, Japanese, Korean) multi-stage goals and script-weighted length instead of relying on English-only word patterns plus raw character count. Equivalent goals translated between English, Chinese, Japanese, and Korean no longer change Single/Team topology in the routing stability gate. Existing English and Chinese outcomes, including structural-pattern regressions, retain their previous behavior. Script weighting intentionally changes a detailed, long English single-action goal from `team` to `single` when its estimated information length remains bounded; this case is locked by a regression test. Multilingual applications may also observe corrected automatic routes for CJK structured goals.
|
||||
The next major release changes automatic `runTeam()` from deterministic-only to
|
||||
Hybrid by default. A short goal may therefore make one additional model call
|
||||
and upgrade from Single to Team, increasing latency, token use, and cost.
|
||||
Applications that require exact old call counts or fully offline routing should
|
||||
set `executionRouting: { strategy: 'deterministic' }` before upgrading.
|
||||
|
||||
Shadow evaluation is a release-engineering technique, not a user-facing runtime
|
||||
mode: run fixed fixtures in CI and canaries, compare its recommendation without
|
||||
changing production topology, and promote only after the documented accuracy,
|
||||
invalid-output, cost, and latency gates pass. Online historical-success learning
|
||||
and Team-to-Single optimization are outside V1.
|
||||
Reference in new issue
Block a user