Skip to content
中文

JSON value transport: validate structured results directly ​

Generate JSON collection and parsing from an output Schema without adding a tool-selection envelope, and return a unified model result.

The json mode is enabled by default; CompatibleModelProvider uses json_object. When array or scalar output requires turning that provider mode off, set options.json=false explicitly, and the same JSON decoding and Schema validation still run.

createJsonTransport({id,outputSchema,options?}) returns an implementation that satisfies the Core ModelTransportDefinition<T> contract and preserves the id literal. outputSchema is a SchemaAdapter<T> containing the JSON Schema and a synchronous parser; it can be a plain object, a Support Schema implementation, or a custom class. The parser is also called after JSON decoding, so neither the Schema declaration nor the model output can replace runtime validation.

Each model call creates a new collector and does not share fragment caches. The collector accepts text fragments; function-call fragments, invalid JSON, Schema validation failures, and asynchronous parsers are all rejected. The Runner continues to own input, Schema, output budget, cancellation, and call quota; this helper does not create extra runners or widen permissions.

The model output is directly the JSON value of that Schema, and the call result is still {value,invocation}. It has no tool/input envelope and does not require a tool catalog. Use createModelTransport/createStageModelTransport when the model must select tools. The Provider decides the JSON wire format and which value types are actually supported; nothing is inferred from the model name.

Progressive examples for the same business case ​

Minimal JSON summary: bind Schema and parser in one step ​

Beginner · Node.js

ts
import { ModelRunner, Support } from '@jangts/agent-core';
const summary = Support.createJsonTransport({ id: 'summary', outputSchema: {
  jsonSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'], additionalProperties: false },
  parse(value: unknown) {
    if (!value || typeof value !== 'object' || !('text' in value) || typeof value.text !== 'string') throw new TypeError('需要摘要正文');
    return { text: value.text };
  },
} });
const provider = { async *stream() { yield '{"text":"服务运行正常。"}'; } };
const model = new ModelRunner({ provider, transports: [summary] });
const result = await model.invoke({ input: '概括服务状态', transport: summary });
console.log(result.value.text, result.invocation);
js
import { ModelRunner, Support } from '@jangts/agent-core';
const summary = Support.createJsonTransport({ id: 'summary', outputSchema: {
        jsonSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'], additionalProperties: false },
        parse(value) {
            if (!value || typeof value !== 'object' || !('text' in value) || typeof value.text !== 'string')
                throw new TypeError('需要摘要正文');
            return { text: value.text };
        },
    } });
const provider = { async *stream() { yield '{"text":"服务运行正常。"}'; } };
const model = new ModelRunner({ provider, transports: [summary] });
const result = await model.invoke({ input: '概括服务状态', transport: summary });
console.log(result.value.text, result.invocation);

Add temperature, budget, and a custom parser to the same summary contract ​

Extension · Node.js

Both examples use offline Providers. When switching providers, the same transport and call contract continue to apply.

ts
import { ModelRunner, Support } from '@jangts/agent-core';
class SummarySchema {
  readonly jsonSchema = { type: 'object', properties: { text: { type: 'string' } }, required: ['text'], additionalProperties: false };
  #maxChars = 100;
  parse(value: unknown) {
    if (!value || typeof value !== 'object' || !('text' in value) || typeof value.text !== 'string'
      || !value.text.trim() || value.text.length > this.#maxChars) throw new TypeError('需要简短摘要');
    return { text: value.text };
  }
}
const summary = Support.createJsonTransport({ id: 'summary', outputSchema: new SummarySchema(), options: { temperature: 0.2 } });
const model = new ModelRunner({ provider: { async *stream() { yield '{"text":"服务运行正常。"}'; } },
  transports: [summary], maxCalls: 2, maxOutputTokens: 256,
});
console.log((await model.invoke({ input: '概括服务状态', transport: 'summary' })).value.text);
js
import { ModelRunner, Support } from '@jangts/agent-core';
class SummarySchema {
    jsonSchema = { type: 'object', properties: { text: { type: 'string' } }, required: ['text'], additionalProperties: false };
    #maxChars = 100;
    parse(value) {
        if (!value || typeof value !== 'object' || !('text' in value) || typeof value.text !== 'string'
            || !value.text.trim() || value.text.length > this.#maxChars)
            throw new TypeError('需要简短摘要');
        return { text: value.text };
    }
}
const summary = Support.createJsonTransport({ id: 'summary', outputSchema: new SummarySchema(), options: { temperature: 0.2 } });
const model = new ModelRunner({ provider: { async *stream() { yield '{"text":"服务运行正常。"}'; } },
    transports: [summary], maxCalls: 2, maxOutputTokens: 256,
});
console.log((await model.invoke({ input: '概括服务状态', transport: 'summary' })).value.text);

Policies & implementations ​

API reference, usage examples and developer guides.