@automators/assistant
v1.2.0
Published
Shared Automators assistant UI, contracts, persistence schema, and host-authorized agent loop.
Readme
@automators/assistant
Shared assistant UI and runtime contracts for Automators applications. Every application mounts its own instance and supplies its signed-in identity, prompt, model, storage and host-authorized tool executor. The package never holds an API key or a credential with more authority than the host user.
Published publicly on npmjs.org under the MIT license.
The package is public and has no runtime dependency on the token package.
Consumers load their vendored design-token CSS before styles.css; the
assistant stylesheet only references the published token variables.
import { assertAssistantContext } from "@automators/assistant";
import { runAssistantTurn } from "@automators/assistant/server";
import { AssistantPanel } from "@automators/assistant/react";
import "@/design-tokens/tokens.css"; // the host's vendored token entrypoint
import "@automators/assistant/styles.css";AssistantSurface and the configurable MessageList are the zero-regression
path for an established product: keep product-only controls in host renderers
while the package owns the context boundary and transcript viewport behavior.
Structural assistant messages that contain tool calls but no visible text stay
in the durable transcript and are hidden by the default message renderer.
Tool transport
New consumers should declare transport explicitly in AssistantContext:
const context = {
appKey: "operator",
systemPromptFragment: "Use only host-authorized tools.",
currentPage: "/routines",
userPermissions: ["routines:read"],
identity: { userId: "user-1" },
toolTransport: { kind: "in-process" },
};MCP-backed hosts use { kind: "mcp", endpoint: "/api/mcp" }. The legacy
mcpEndpoint field remains accepted for existing consumers.
Runtime and approval
runAgentLoop remains available and now checkpoints accepted conversation
progress before model calls, after assistant/tool messages, and on controlled
failure or abort.
runAssistantTurn adds an approval-capable turn contract. Tool definitions are
fail-closed in this API: a tool executes immediately only when
approvalRequired: false; every other tool requires an approval adapter.
The host owns the durable AssistantApprovalAdapter. Its consume method is
the single-use security boundary and must atomically return the recorded call
only when the approval is still pending and belongs to the current owner and
conversation. The browser sends only an approval id and approve/reject decision;
it never resubmits tool arguments.
The host executor remains the authorization boundary and must repeat the live permission checks used by the application's normal MCP/API path when a tool is actually executed. Approval never grants permission. HTTP MCP tokens, model selection, authorization and persistence implementations stay in the consumer.
Adapter metadata
A model adapter can return metadata on its AssistantModelCompletion, and
the runtime persists it verbatim on the assistant message that completion
produces. It comes back to the adapter on every later complete() call as
message.metadata. The runtime treats the value as opaque: it never reads a
field, and it stores nothing when the adapter omits metadata or returns a
non-object.
The canonical use is a provider's thinking blocks, which must be replayed unchanged alongside the tool call they produced:
const model = {
async complete({ messages }) {
const response = await client.messages.create({
messages: toProviderMessages(messages), // reads message.metadata
// ...
});
return {
content: textOf(response),
toolCalls: toolCallsOf(response),
metadata: { thinking: thinkingBlocksOf(response) },
};
},
};Available from 1.2.0. Consumers on earlier versions had to attach such data to a tool-call object to keep it in the transcript.
Conversation records remain schemaVersion: 1. Tool-call history and runtime
checkpoint state are backward-compatible optional fields. Consumers pin this
package version and implement ConversationStorageAdapter; they never copy its
source.
