Skip to content
中文

ModelCalls: external inference bindings ​

Bind identity, validation, cancellation, and a unified invocation receipt for App-defined I/O such as embeddings.

The constructor registers {id,identity,invoke,assertInput?,assertOutput?}. invoke({modelId,input,timeoutMs},execution) returns ModelResult<Output>, with the body/vector in value and real call information in invocation. Input and output types can be inferred from the registered tuple for known literal IDs; unknown IDs are rejected. identity states the real model/algorithm version and is not guessed from the request.

timeoutMs must be a positive safe integer within the supported range and is merged with the caller's signal. Input and output assertions are synchronous and must return void; a late result after cancellation is not returned as success. The underlying I/O should consume the provided signal; stopping the wait does not undo external side effects.

This is an independent external inference adapter, and returning a similar shape does not mean it is wired into the chat Runner's call-count ledger. The App must explicitly carry the corresponding business budget for current source bindings; embedding and chat calls cannot be charged against each other's units. Core's single-run multi-model chat still uses the normal Engine/ModelRunner model contract.

Progressive examples for the same business case ​

First bind an offline demonstration vector algorithm ​

Beginner · Node.js

The algorithm only demonstrates I/O binding and does not provide real language embedding quality.

ts
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
  { id: 'demo-vector', identity: 'length-direction-v1', invoke: (text: string) => [text.length, 1] },
] as const);
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: new AbortController().signal });
console.log(result.value, result.invocation.modelId);
js
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
    { id: 'demo-vector', identity: 'length-direction-v1', invoke: (text) => [text.length, 1] },
]);
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: new AbortController().signal });
console.log(result.value, result.invocation.modelId);

Add input and output checks plus cancellation to the same invoke ​

Configuration · Node.js

ts
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
  { id: 'demo-vector', identity: 'length-direction-v1',
    assertInput(text: string) { if (!text.trim()) throw new Error('文本为空'); },
    invoke(text: string, context) { context.signal.throwIfAborted(); return [text.length, 1]; },
    assertOutput(vector: number[]) { if (vector.length !== 2 || vector.some(value => !Number.isFinite(value))) throw new Error('向量无效'); },
  },
] as const);
const controller = new AbortController();
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: controller.signal });
console.log(models.identity('demo-vector'), result.value);
js
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
    { id: 'demo-vector', identity: 'length-direction-v1',
        assertInput(text) { if (!text.trim())
            throw new Error('文本为空'); },
        invoke(text, context) { context.signal.throwIfAborted(); return [text.length, 1]; },
        assertOutput(vector) { if (vector.length !== 2 || vector.some(value => !Number.isFinite(value)))
            throw new Error('向量无效'); },
    },
]);
const controller = new AbortController();
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: controller.signal });
console.log(models.identity('demo-vector'), result.value);

Policies & implementations ​

API reference, usage examples and developer guides.