Output
A mind acts with kernel.output. It is never refused: the kernel records it and passes it to the
body, which clamps it to the control's limits. From a sync system, outputs are made when the run
lands, in the order they were made, with its writes; from an async one, as they are made.
kernel.output<K extends OutputType>(type: K, data: OutputData[K]): Promise<void>
Output
type OutputData = {
"cognet:output:text": { channel: string; content: string; format?: "json" | "markdown"; chunk?: Chunk }
"cognet:output:audio": { channel: string; ref: Ref; transcript?: string; durationMs?: number; chunk?: Chunk }
"cognet:output:visual": { channel: string; ref: Ref; kind: "image" | "video"; caption?: string; chunk?: Chunk }
"cognet:output:vector": {
channel: string
values: number[]
unit?: string
units?: string[]
labels?: string[]
profile?: string
basis?: number
chunk?: Chunk
}
}
type Chunk = { of: string; final?: boolean }
type Ref = { uri: string; mime: string; bytes?: number }
Fields
| Field | Kinds | Is |
|---|---|---|
channel | all | the control it drives. Required — never defaulted |
content | text | the text |
format | text | json or markdown; absent is plain prose |
ref | audio, visual | where the bytes are |
transcript | audio | what it says |
caption | visual | what it shows |
kind | visual | image or video |
values | vector | one act: every component of the control, in the order it declared them |
unit, units, labels, profile | vector | as on a stimulus |
basis | vector | the sensed stamp of the newest reading this was decided on |
chunk | all | { of, final } — part of a longer output: same of on every part, final on the last |
Examples
// drive two wheels — one act, both at once
await kernel.output("cognet:output:vector", { channel: "/wheels", values: [0.4, 0.4], basis: sensed })
// say something, streamed
await kernel.output("cognet:output:text", { channel: "/chat", content: "On my ", chunk: { of: "reply-7" } })
await kernel.output("cognet:output:text", { channel: "/chat", content: "way.", chunk: { of: "reply-7", final: true } })
Control
What the body declares about each control, from kernel.body().controls. A mind can only drive what is listed.
type Control = VectorControl | TextControl | AudioControl
type VectorControl = {
kind: "vector"
channel: string
profile?: string
frame?: string
components: ControlComponent[]
lapse: Lapse
rate?: number
trajectory?: { points: number; interpolation: "step" | "linear" }
}
type TextControl = { kind: "text"; channel: string; profile?: string }
type AudioControl = { kind: "audio"; channel: string; profile?: string; sampleRate: number; channels: number }
type ControlComponent = {
name: string
unit: string
range?: [number, number]
categories?: string[]
interface: "switch" | "axis" | "choice" | "position" | "velocity" | "effort"
joint?: string
slew?: number
}
type Lapse =
| { kind: "release"; after: number }
| { kind: "keep" }
| { kind: "behaviour"; after: number; name: string; describe: string }
| Field | Is |
|---|---|
channel | where outputs for it go |
frame | whose axes its values are in — a part of the body, or a place |
components | each value in values, in order |
lapse | what the body does when outputs stop |
rate | how often the body reads it — outputs sent faster are superseded unseen |
trajectory | it takes up to points timed points, held (step) or moved towards (linear) |
interface
| Value | Driven as |
|---|---|
switch | on or off |
axis | −1 to 1 |
choice | an index into categories |
position | a target, in its unit |
velocity | a speed, in its unit |
effort | a force or torque, in its unit |
A component's range and slew — the most it may change in a second — are enforced by the body.
lapse
| Kind | After after ms with no output |
|---|---|
release | every component lets go: off, zero, limp |
keep | the last output stays applied — targets only, never a velocity or effort |
behaviour | the body runs a behaviour of its own, name, described in describe |
Skills
A task the body can carry out — walk to a place, craft a tool — is a skill, not an output.
It goes through kernel.run, checked against policy, and answers with progress and a result.
A control loop never uses kernel.run.