Skip to content
中文

createContextReductionNode ​

SUPPORT · function · Runtime value

Create a node that applies exactly one registered reduction step.

Partial plans keep the full budget until final assembly, so intermediate nodes do not shrink the allowance reserved for the reply.

Import ​

ts
import { createContextReductionNode } from '@jangts/agent-core/support';
js
import { createContextReductionNode } from '@jangts/agent-core/support';

Other public entry points:@jangts/agent-core/support, @jangts/agent-core/support/context.

Definition ​

Type parameters ​

Type parameterConstraintDefault type
State——
Result——
App—undefined

Call ​

ts
createContextReductionNode<State, Result, App = undefined>(definition: ContextReductionNodeDefinition<State, Result, App>): WorkflowNode<State, Result, App>

Create a node that applies exactly one registered reduction step.

Partial plans keep the full budget until final assembly, so intermediate nodes do not shrink the allowance reserved for the reply.

Type parameterConstraintDefault type
State——
Result——
App—undefined
ParameterTypePassingDescription
definitionContextReductionNodeDefinition<State, Result, App>Required—
Fields of definition
FieldTypeRequiredDescription
idstringRequiredRead-only. Stable node id referenced by routes and error handling.
descriptionstringRequiredRead-only. Required explanation of what the node does; also used in diagnostics.
namestring | undefinedOptionalRead-only. Display name; defaults to id when omitted.
requiresreadonly (keyof State & string)[] | undefinedOptionalRead-only. State keys that must be present before this node runs; enforced by the engine.
providesreadonly (keyof State & string)[] | undefinedOptionalRead-only. State keys this node is expected to produce; validated after run.
routesreadonly WorkflowRoute<State, Result, App>[]RequiredRead-only. Candidate successors, evaluated in order. A getter must be pure; registration reads it once.
startsRoundboolean | undefinedOptionalRead-only. Reserves a fresh round on entry. Use it for steps that may legitimately repeat; entering such a node when the round budget is exhausted fails with the configured exhausted error.
onErrorNodeIdstring | undefinedOptionalRead-only. Node entered when run/provides/route fails; contract errors always propagate instead.
onErrorRouteIdstring | undefinedOptionalRead-only. Route id reported with the recovery transition.
prepared((state: Readonly<State>, context: WorkflowContext<App>) => PreparedModelCall) | undefinedOptionalRead-only. Optional prebuilt model call, used instead of preparing request.
plan(state: Readonly<State>, context: WorkflowContext<App>) => ContextPlanRequiredRead-only. Builds the context plan; must be synchronous so budget failures surface before any I/O.
request(ModelPrepareRequest<string | ModelTransportDefinition<unknown>> & { modelId?: string; }) | ((state: Readonly<State>, context: WorkflowContext<App>) => ModelPrepareRequest<string | ModelTransportDefinition> & { modelId?: string; }) | undefinedOptionalRead-only. Model preparation request, either static or derived from the current node state.
policyContextPolicy | undefinedOptionalRead-only. Processing policy; omitted means validate (no reduction, audit checks only).
timeoutMsnumber | undefinedOptionalRead-only. Per-node timeout in milliseconds; defaults to the Core call timeout.
compressorsreadonly ContextCompressor[] | undefinedOptionalRead-only. Compressors referenced by compression steps; validated against the policy at creation.
selectorsreadonly ContextSelector[] | undefinedOptionalRead-only. Selectors referenced by model-driven selection; validated against the policy at creation.
stepIdstring | ((state: Readonly<State>) => string)RequiredRead-only. ID of the reduction step to run, fixed or derived from state.
update(result: ContextStageResult, state: Readonly<State>) => Partial<State>RequiredRead-only. Receives the stage result after one reduction has been applied.

Returns: WorkflowNode<State, Result, App>.

Return value structure
FieldTypeRequiredDescription
idstringRequiredRead-only. Stable node id referenced by routes and error handling.
descriptionstringRequiredRead-only. Required explanation of what the node does; also used in diagnostics.
namestring | undefinedOptionalRead-only. Display name; defaults to id when omitted.
report((update: void | Readonly<Partial<State>>, context: NodeReportingContext) => WorkflowNodeReport) | undefinedOptionalRead-only. Optional application-reported detail, collected only when content logging is enabled.
startsRoundboolean | undefinedOptionalRead-only. Reserves a fresh round on entry. Use it for steps that may legitimately repeat; entering such a node when the round budget is exhausted fails with the configured exhausted error.
onErrorNodeIdstring | undefinedOptionalRead-only. Node entered when run/provides/route fails; contract errors always propagate instead.
onErrorRouteIdstring | undefinedOptionalRead-only. Route id reported with the recovery transition.
requiresreadonly (keyof State & string)[] | undefinedOptionalRead-only. State keys that must be present before this node runs; enforced by the engine.
providesreadonly (keyof State & string)[] | undefinedOptionalRead-only. State keys this node is expected to produce; validated after run.
routesreadonly WorkflowRoute<State, Result, App>[]RequiredRead-only. Candidate successors, evaluated in order. A getter must be pure; registration reads it once.
run((state: Readonly<State>, context: WorkflowContext<App>) => void | Partial<State> | Promise<void | Partial<State>>) | undefinedOptionalRead-only. Return only changed fields. Core commits them after cancellation and output checks.

Examples ​

Validate and assemble only, without compression yet ​

Beginner · Node.js

ts
import { AgentCoreEngine, defineWorkflow, route } from '@jangts/agent-core/engine';
import { Support } from '@jangts/agent-core';
import type { BuiltContext, PreparedModelCall } from '@jangts/agent-core/types';
type State = { question: string; input?: BuiltContext; prepared?: PreparedModelCall; answer?: string };
const builder = Support.defineContextFragments<State>([
  { id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
], { maxInputChars: 2000 });
const prepare = Support.createContextProcessingNode<State, string>({
  id: 'prepare', description: '装配并校验输入', startsRound: true,
  plan: state => builder.plan({ input: state }),
  update: result => ({ input: result.input, prepared: result.prepared }),
  routes: [route.to('reply')],
});
const workflow = defineWorkflow<State, string>({ id: 'chat', nodes: [prepare, {
  id: 'reply', description: '使用同次准备回答', requires: ['input', 'prepared'],
  async run(state, { model }) { const { value } = await model.invoke({ input: state.input!, prepared: state.prepared! }); return { answer: String(value) }; },
  routes: [route.deliver('answer')],
}] });
const agent = new AgentCoreEngine({ workflow, model: { provider: { async *stream() { yield '服务正常'; } } } });
console.log(await agent.run({ question: '状态?' }));
js
import { AgentCoreEngine, defineWorkflow, route } from '@jangts/agent-core/engine';
import { Support } from '@jangts/agent-core';
const builder = Support.defineContextFragments([
    { id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
], { maxInputChars: 2000 });
const prepare = Support.createContextProcessingNode({
    id: 'prepare', description: '装配并校验输入', startsRound: true,
    plan: state => builder.plan({ input: state }),
    update: result => ({ input: result.input, prepared: result.prepared }),
    routes: [route.to('reply')],
});
const workflow = defineWorkflow({ id: 'chat', nodes: [prepare, {
            id: 'reply', description: '使用同次准备回答', requires: ['input', 'prepared'],
            async run(state, { model }) { const { value } = await model.invoke({ input: state.input, prepared: state.prepared }); return { answer: String(value) }; },
            routes: [route.deliver('answer')],
        }] });
const agent = new AgentCoreEngine({ workflow, model: { provider: { async *stream() { yield '服务正常'; } } } });
console.log(await agent.run({ question: '状态?' }));

Add a history trimming policy to the same node contract ​

Configuration · Node.js

Put this node back into the same Workflow as the previous example; each run just adds history to State, and the model reply node does not change its interface. In a complete flow the reply target must exist.

ts
import { Support } from '@jangts/agent-core';
import { route } from '@jangts/agent-core/engine';
import type { BuiltContext, PreparedModelCall } from '@jangts/agent-core/types';
type State = { question: string; history: { role: string; content: string }[]; input?: BuiltContext; prepared?: PreparedModelCall };
const builder = Support.defineContextFragments<State>([
  { id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
  { id: 'history', sourceId: 'conversation', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 10000, format: state => ({ messages: state.history }) },
], { maxInputChars: 1200 });
const prepare = Support.createContextProcessingNode<State, string>({
  id: 'prepare', description: '按需要裁切旧历史', startsRound: true,
  plan: state => builder.plan({ input: state }),
  policy: { mode: 'reduce', steps: [{ id: 'recent', kind: 'trim', fragmentId: 'history', field: 'messages',
    targetChars: 700, grouping: { kind: 'user-turn' }, keepGroups: 1 }] },
  update: result => ({ input: result.input, prepared: result.prepared }),
  routes: [route.to('reply')],
});
console.log(prepare.id);
js
import { Support } from '@jangts/agent-core';
import { route } from '@jangts/agent-core/engine';
const builder = Support.defineContextFragments([
    { id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
    { id: 'history', sourceId: 'conversation', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 10000, format: state => ({ messages: state.history }) },
], { maxInputChars: 1200 });
const prepare = Support.createContextProcessingNode({
    id: 'prepare', description: '按需要裁切旧历史', startsRound: true,
    plan: state => builder.plan({ input: state }),
    policy: { mode: 'reduce', steps: [{ id: 'recent', kind: 'trim', fragmentId: 'history', field: 'messages',
                targetChars: 700, grouping: { kind: 'user-turn' }, keepGroups: 1 }] },
    update: result => ({ input: result.input, prepared: result.prepared }),
    routes: [route.to('reply')],
});
console.log(prepare.id);

API reference, usage examples and developer guides.