Agent providers
An agent provider recognizes the foreground CLI in one terminal, finds its journal through brokered observation, and maps records into Terminay lifecycle events. It observes a running process; it does not start, control, or receive a raw terminal stream.
Manifest contribution
Request agent-observation and declare an agentProviders entry. The
registered providerId must match that contribution’s id.
| Contribution field | Type and meaning |
|---|---|
id, displayName | Stable provider identity and user-facing name. |
description, icon, platforms | Optional presentation and OS availability metadata. |
processMatchers | Safe declarative matchers: executableName plus optional exact arguments tokens. |
mappings | Declared mappingVersion / providerVersionRange pairs for a provider release. |
requiredEnvironmentVariables | Names that observation.processes.environment() may request from the exact foreground process or a descendant. |
requiredEnvironmentCapabilities | One or more of process-observation, filesystem-observation, and agent-journal. |
Runtime contract
import { defineAgentProvider, jsonlSession } from '@terminay/extension-api';
export const codex = defineAgentProvider({
mappingVersion: '1',
matchesForeground(process) {
return process.executableName === 'codex';
},
async observe(terminal) {
const journal = await terminal.observation.files.resolveHomeRelative(
'.codex/session.jsonl',
);
if (!journal) return { state: 'not-bound' };
const binding = await terminal.bindSession({
providerSessionId: 'session-from-journal',
mappingVersion: '1',
journal,
fingerprint: { kind: 'codex-journal', file: journal },
});
return jsonlSession({
binding,
source: terminal.observation.files.follow(journal, { signal: terminal.signal }),
mapRecord(record, session) {
// Map a provider record and call session.publish.* when appropriate.
},
});
},
});| Member | Signature | Purpose |
|---|---|---|
mappingVersion | string | Version of this journal-to-event mapping. It is stored in the session binding. |
matchesForeground | (process: AgentForegroundProcess) => boolean | Fast, side-effect-free recognition of the terminal’s foreground process. |
observe | (terminal: AgentTerminalContext) => Promise<AgentObservationResult> | Find and bind one session, or report why this terminal has none. |
defineAgentProvider | (provider) => AgentProviderDefinition | Identity helper for a provider definition. |
context.agents.registerProvider | (providerId, runtime) => AgentProviderRegistration | Registers the runtime; add the returned disposable to context.subscriptions. |
Observation results
| Return value | When to use it |
|---|---|
AgentJsonlSession | A bound JSONL session. jsonlSession(options) constructs this form and returns { state: 'bound', ...options }. |
{ state: 'not-bound' } | The process belongs to the provider but a usable session is not present yet. |
{ state: 'unavailable', reason } | The provider cannot observe this terminal. Reasons are environment-capability-missing, process-not-recognized, session-not-found, session-not-bound, unsupported-provider-version, malformed-observation, observation-limit-exceeded, or cancelled. |
AgentTerminalContext provides opaque terminal, project, environment, and process
handles; foreground-process facts; an optional TTY fact; granted capabilities; a cancellation
signal; and observation. See Terminal observation for that broker.
Bind a session
Call terminal.bindSession(request) before returning a bound session. The request
contains a provider-owned providerSessionId, the provider mappingVersion,
optional journal handle, optional display-safe primitive metadata, and a fingerprint.
| Fingerprint field | Allowed value |
|---|---|
kind | A provider-defined string describing the binding strategy. |
process, file | Only the opaque process or file handles issued for this terminal context. |
metadata | A record of bounded JSON primitives; no paths, credentials, or raw records. |
The host returns an opaque AgentSessionBinding. It carries the provider session ID,
mapping version, and optional journal handle, but is valid only in the terminal context that issued it.
JSONL sessions
An AgentJsonlSession has a root binding, a root AgentFileWatcher, and
mapRecord(record, session). It may also include fixed childSources or
asynchronous childSourceDiscovery; every child has a stable childId, its
own journal handle, and watcher, but shares the root binding.
The mapper receives the binding, journal role (root or a child ID), a
lifecycle publisher, and a cancellation signal. See Lifecycle events for the publisher contract.