Skip to content
中文

Model tools and transports: typed selection only after full validation ​

A tool definition provides a Schema and resolver; a transport translates wire output into the unified model selection contract.

A tool list describes what the model may propose, not what business authorization has been granted. inputSchema.parse parses arguments, and resolve constructs a domain result from the complete, validated input. Both are synchronous and cannot secretly execute network tools.

select returns a sealed stage subset. Unknown tools, duplicate IDs, empty selections, or selections outside the stage are rejected. The App decides tool visibility before projection; real request permissions should still be checked during tool execution.

Core obtains options, schemaChars, an optional instruction, and a new collector through ModelTransportDefinition.prepare. collector.push accepts fragments; finish returns the result after protocol and input validation.

Core reads outputChars after the collector factory returns, after every push, and after finish: the value must be a non-negative safe integer, and NaN, Infinity, negative numbers, and fractions are rejected as protocol errors. maxOutputChars can be explicitly set to Infinity, but that does not relax the collector counting contract. Diagnostics keep the peak of each valid observation; finish may release or normalize internal buffers, so the buffer is not required to grow forever.

Native interaction accepts strings or valid function-call-delta. A function fragment must be a non-array object with index 0; id, when provided, must be a non-empty string, and name and arguments, when provided, must be strings. Conflicting IDs, multiple calls, unregistered tools, mixed body text, or incomplete arguments are rejected and no tool is executed.

The optional call metadata on the collector is read only once on a best-effort basis; a throwing getter does not override the business result already obtained, the original error, or cancellation, and does not prevent model.end from finishing. outputChars is an execution validation field and is not subject to this tolerance rule. Plain objects or classes can both implement this interface; Support provides a recommended native/JSON combination without requiring Core to depend on Support.

Progressive examples for the same business case ​

Declare two selectable tools ​

Beginner · Node.js

ts
import { ModelToolRegistry } from '@jangts/agent-core';
const inputSchema = { jsonSchema: { type: 'object', properties: {}, additionalProperties: false },
  parse(value: unknown) {
    if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).length) throw new Error('需要空对象');
    return {};
  } };
const tools = new ModelToolRegistry([
  { id: 'greet', description: '回答问候', inputSchema, resolve: () => 'greet' },
  { id: 'status', description: '查询状态', inputSchema, resolve: () => 'status' },
]).seal();
console.log(tools.resolve({ toolId: 'status', input: {} }, { stageId: 'recognize' }));
js
import { ModelToolRegistry } from '@jangts/agent-core';
const inputSchema = { jsonSchema: { type: 'object', properties: {}, additionalProperties: false },
    parse(value) {
        if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).length)
            throw new Error('需要空对象');
        return {};
    } };
const tools = new ModelToolRegistry([
    { id: 'greet', description: '回答问候', inputSchema, resolve: () => 'greet' },
    { id: 'status', description: '查询状态', inputSchema, resolve: () => 'status' },
]).seal();
console.log(tools.resolve({ toolId: 'status', input: {} }, { stageId: 'recognize' }));

Project an allowed subset to only one stage ​

Configuration · Node.js

ts
import { ModelToolRegistry, Support } from '@jangts/agent-core';
const schema = Support.defineSchema({ jsonSchema: { type: 'object', properties: {} },
  parse(value: unknown) { if (!value || typeof value !== 'object' || Array.isArray(value)) throw new TypeError('需要对象'); return {}; } });
const registry = new ModelToolRegistry([
  { id: 'greet', description: '问候', inputSchema: schema, resolve: () => 'greet' },
  { id: 'status', description: '状态', inputSchema: schema, resolve: () => 'status' },
]).seal();
const readOnly = registry.select(['status']);
const transport = Support.createModelTransport({ id: 'recognize', tools: readOnly });
console.log(transport.id, readOnly.ids());
js
import { ModelToolRegistry, Support } from '@jangts/agent-core';
const schema = Support.defineSchema({ jsonSchema: { type: 'object', properties: {} },
    parse(value) { if (!value || typeof value !== 'object' || Array.isArray(value))
        throw new TypeError('需要对象'); return {}; } });
const registry = new ModelToolRegistry([
    { id: 'greet', description: '问候', inputSchema: schema, resolve: () => 'greet' },
    { id: 'status', description: '状态', inputSchema: schema, resolve: () => 'status' },
]).seal();
const readOnly = registry.select(['status']);
const transport = Support.createModelTransport({ id: 'recognize', tools: readOnly });
console.log(transport.id, readOnly.ids());

API reference, usage examples and developer guides.