Skip to content
中文

route: generating complete configuration and capturing common checks ​

The route function group generates ordinary WorkflowRoute configuration; hand-written objects and generated configuration follow the same contract.

The first argument of every to* generator is the target node. route(target, id?) is an alias of route.to, and only its second argument and that of to is directly an optional route ID. Condition generators accept id, conditionId, and description in options; these can usually be omitted.

GeneratorCheck and result
to(target, id?)No when; jumps directly
toIf(target, options?)Reads the same-named state field as a Boolean: Boolean(state[target])
toIfDefined(target, field, options?)The field is not undefined; null, false and 0 also count as defined
toIfError(target, options?)By default checks whether error is defined; errorKey selects another field
toIfNotEmpty(target, key, options?)The length of a known array is greater than 0; it is not a general empty-value check for arbitrary values
toIfEqual(target, path, value, options?)The value read from path is strictly equal to the fixed value
toIfEqualWith(target, leftPath, rightPath, options?)The values read from two state paths are strictly equal
deliver(field, options?)Ends and reads the required field; undefined is rejected
deliverIfReady(field, options?)Ends only when the field is defined, otherwise continues matching the next route
deliverWhenComplete(field, options?)Ends only when StepOutcome.type is complete and takes its value

The two Equal generators support dot paths such as profile.items.0.id; the current parameters of toIfDefined and toIfNotEmpty are field keys, and they must not be assumed to support paths. Strict equality does not deep-compare objects; when two missing paths both yield undefined they compare equal, so a preceding check should be configured when the business does not accept that.

Existing to* generators generally generate to-target from the target; toIfEqual generates an ID from the path, value, and target combination it can express stably, and toIfEqualWith generates one from the left and right paths and the target; symbol paths or non-scalar equal values cannot produce the same stable default ID. The deliver family conventionally uses complete. These are conventions of the specialized functions, not a uniform naming constraint imposed by Workflow.

Generators commonly use conditionId: {nid}.{rid}. Plain hand-written objects support the same two placeholders; Workflow only expands node values and the final local route ID, appends suffixes such as ~2 for duplicate route IDs, and does not guess IDs or specialized-function rules that were not provided.

Progressive examples for the same business case ​

Minimal jump and end ​

Beginner · Node.js

ts
import { route } from '@jangts/agent-core/engine';
const jump = route('reply');
const sameJump = route.to('reply');
const finish = route.deliver('answer');
console.log(jump, sameJump, finish);
js
import { route } from '@jangts/agent-core/engine';
const jump = route('reply');
const sameJump = route.to('reply');
const finish = route.deliver('answer');
console.log(jump, sameJump, finish);

Common branches for the same business ​

Configuration · Node.js

ts
import { route } from '@jangts/agent-core/engine';
const reviewRoutes = [
  route.toIfError('failure'),
  route.toIf('recovered'),
  route.toIfNotEmpty('candidate', 'candidates'),
  route.toIfDefined('reply', 'answer'),
  route.toIfEqual('status', 'intent.id', 'status'),
  route.toIfEqualWith('reuse', 'cache.0.id', 'request.id'),
  route.to('fallback'),
];
const completionRoutes = [route.deliverIfReady('answer'), route.to('retry')];
const outcomeRoutes = [route.deliverWhenComplete('outcome'), route.to('retry')];
console.log(reviewRoutes, completionRoutes, outcomeRoutes);
js
import { route } from '@jangts/agent-core/engine';
const reviewRoutes = [
    route.toIfError('failure'),
    route.toIf('recovered'),
    route.toIfNotEmpty('candidate', 'candidates'),
    route.toIfDefined('reply', 'answer'),
    route.toIfEqual('status', 'intent.id', 'status'),
    route.toIfEqualWith('reuse', 'cache.0.id', 'request.id'),
    route.to('fallback'),
];
const completionRoutes = [route.deliverIfReady('answer'), route.to('retry')];
const outcomeRoutes = [route.deliverWhenComplete('outcome'), route.to('retry')];
console.log(reviewRoutes, completionRoutes, outcomeRoutes);

Override identity as the business requires; hand-written objects also support placeholders ​

Extension · Node.js

conditionId carries no authorization. It helps logs explain which condition matched.

ts
import { defineWorkflow, route } from '@jangts/agent-core/engine';
type State = { answer?: string; reviewError?: string };
const workflow = defineWorkflow<State, string>({ id: 'review', nodes: [
  { id: 'check', description: '检查既有结果', startsRound: true, routes: [
    route.toIfError('failure', { errorKey: 'reviewError', id: 'review-error' }),
    { id: 'ready', conditionId: '{nid}.{rid}', when: state => state.answer !== undefined,
      complete: state => state.answer! },
    route.to('failure'),
  ] },
  { id: 'failure', description: '给出当前缺失信息',
    run: () => ({ answer: '当前没有可交付结果' }), routes: [route.deliver('answer')] },
] });
console.log(workflow.describe());
js
import { defineWorkflow, route } from '@jangts/agent-core/engine';
const workflow = defineWorkflow({ id: 'review', nodes: [
        { id: 'check', description: '检查既有结果', startsRound: true, routes: [
                route.toIfError('failure', { errorKey: 'reviewError', id: 'review-error' }),
                { id: 'ready', conditionId: '{nid}.{rid}', when: state => state.answer !== undefined,
                    complete: state => state.answer },
                route.to('failure'),
            ] },
        { id: 'failure', description: '给出当前缺失信息',
            run: () => ({ answer: '当前没有可交付结果' }), routes: [route.deliver('answer')] },
    ] });
console.log(workflow.describe());

Policies & implementations ​

API reference, usage examples and developer guides.