v3.0.0 Release Notes

Glove 3.0.0 lands four big shifts: first-class subagents with a factory pattern, a guaranteed-symmetric event system for hooks/skills/subagents, sub-stores for per-run cost attribution, and a default MemoryStore in glove-core so a fresh Glove works without any store wiring.

Alongside core, four packages ship at 0.5.0 as early-access: glove-mcp, glovebox-core, glovebox-kit, glovebox-client.

Highlights

Updated packages

PackageVersion
glove-core3.0.0
glove-react3.0.0
glove-voice3.0.0
glove-next3.0.0

New / promoted packages (early-access at 0.5.0)

Four packages ship as 0.5.0. They're production-grade but the surface is still solidifying — semver-minor bumps may land in 0.6.x.

PackageWhat it does
glove-mcpMCP server bridging. mountMcp reloads previously-activated servers and registers the discovermcp discovery subagent. Promoted from internal use to a stable surface. MCP guide →
glovebox-coreAuthoring kit and glovebox build CLI. Wrap a built Glove runnable, run glovebox build, ship the resulting Dockerfile or nixpacks bundle to any container host. Glovebox guide →
glovebox-kitIn-container runtime. Hosts a Glove agent behind a single authenticated WebSocket plus an HTTP /files route for outputs. Most consumers don't import this directly — glovebox build generates a server entry that uses it.
glovebox-clientClient SDK for talking to a deployed Glovebox server. One WebSocket per session, multiple prompts multiplexed. Streams subscriber events and display slot pushes; resolves with the final assistant message and an outputs map of FileRefs.

Deprecated

glove-sqlite is deprecated and will not receive new features. The new MemoryStore in glove-core covers most prototyping needs; for production durability, BYO StoreAdapter. The package still installs and works, just without createSubAgentStore support.

Breaking changes

1. StoreAdapter.addTokens(args: TokenConsumptionCounter)

Was (count: number). The counter is { tokens_in: number; tokens_out: number } — the framework now records both directions separately, useful for per-direction cost reporting. getTokenCount() still returns a single sum. Affects every custom StoreAdapter.

my-store.tstypescript
// Before
async addTokens(count: number) {
  this.tokens += count
}

// After
async addTokens(args: TokenConsumptionCounter) {
  this.tokens += args.tokens_in + args.tokens_out
}

In glove-react, the same change applies to RemoteStoreActions.addTokens(sessionId, args: TokenConsumptionCounter) — breaking for any consumer wiring custom remote-store actions.

2. defineMentiondefineSubAgent (factory pattern)

defineMention(args) is removed. The whole Mention* family of types is replaced by SubAgent*. The shape changed too: instead of returning string content, the factory builds and returns a fully-built child Glove. The framework calls child.processRequest(prompt, signal) and uses the final agent text as the tool result.

lib/agent.tstypescript
// Before
glove.defineMention({
  name: "researcher",
  handler: async ({ prompt, controls }) => {
    return "research result"
  },
})

// After
import { Glove, MemoryStore } from "glove-core"

glove.defineSubAgent({
  name: "researcher",
  description: "Deep web research subagent",
  factory: async ({ parentStore, parentControls, prompt, name }) => {
    const subStore = await parentStore.createSubAgentStore?.(name, false)
      ?? new MemoryStore(`${name}_${Date.now()}`)

    return new Glove({
      store: subStore,
      model: parentControls.glove.model,
      displayManager: parentControls.displayManager,
      systemPrompt: "You are a researcher.",
      compaction_config: {
        compaction_instructions: "Summarize research progress.",
      },
    })
      .fold(searchTool)
      .fold(fetchTool)
      .build()
  },
})

The agent invokes the subagent through the auto-registered glove_invoke_subagent tool — the user's @subagent-name text in messages still reaches the model verbatim as a routing nudge.

3. glove-mcp: discoveryTooldiscoverySubAgent; find_capabilitydiscovermcp

discoveryTool({...}) is renamed discoverySubAgent({...}) and now returns DefineSubAgentArgs (used with glove.defineSubAgent(...) instead of glove.fold(...)). The discovery subagent's name is discovermcp (was find_capability); the model invokes via glove_invoke_subagent({ name: "discovermcp", prompt: "..." }).

mountMcp consumers don't need to change anything — it wires the new shape internally. Update any system prompt that mentions the old name:

lib/agent.tstypescript
// Before
systemPrompt:
  "When the user asks for an external integration, " +
  "call find_capability to discover and activate the right MCP server."

// After
systemPrompt:
  "When the user asks for an external integration, " +
  "invoke the `discovermcp` subagent (via the `glove_invoke_subagent` tool) " +
  "with a brief description of what you need."

4. Hook / skill directives — placeholders, not stripped

User text containing /skill-name or /hook-name directives is no longer stripped from the persisted user message. Each bound directive is replaced by a non-triggerable placeholder of the form [invoked_extension__hook_<name>] or [invoked_extension__skill_<name>]. Hook and skill handlers receive parsedText containing the placeholder, not the bare directive.

UIs that previously rendered raw user text now see the placeholder embedded in the message body. If you need the original text (e.g. for a hook that rewrites the message), read the new Message.pre_modified_text field.

5. Tool.run and GloveFoldArgs.do gain optional signal

Tool.run(input, handOver?, signal?) — backward-compatible; tools that ignore the third arg still work. GloveFoldArgs.do(input, display, glove, signal?) similarly gains an optional fourth signal. Tools that perform long-running internal work (subagent dispatchers, fetches) should forward it so abort propagates all the way down.

What's new

Subscriber events

Five new SubscriberEvent variants:

Bracket symmetry is guaranteed. The Executor brackets every glove_invoke_subagent call regardless of outcome, so a parent-side abort that cuts the dispatcher's promise still produces a matching close bracket. Subscribers can model subagent runs as a stack and trust the brackets.

Sub-stores

StoreAdapter.createSubAgentStore?(namespace, durable?) is a new optional hook. With durable: false (default) it returns a fresh child store per call; with durable: true it returns a cached child for the namespace, so a subagent can carry message history across invocations.

The new MemoryStore in glove-core implements this out of the box, so subagents derived via the standard factory pattern get isolated child stores automatically.

MemoryStore in glove-core

A comprehensive in-memory StoreAdapter is now exported from glove-core. It implements the full surface (messages, tokens, turns, tasks, permissions, inbox, sub-stores) and is used as the default when Glove is constructed without a store.

lib/agent.tstypescript
import { Glove, MemoryStore, Displaymanager, createAdapter } from "glove-core"

const agent = new Glove({
  store: new MemoryStore("session"),  // optional — default is a fresh MemoryStore
  model: createAdapter({ provider: "anthropic" }),
  displayManager: new Displaymanager(),
  systemPrompt: "You are a helpful assistant.",
  compaction_config: { compaction_instructions: "Summarize so far." },
}).build()

Display stack sharing for subagents

AgentControls exposes the parent's displayManager directly so subagent factories can build a child Glove that pushes UI to the parent's display stack. New setDisplayManager(dm) on IGloveRunnable / IGloveBuilder lets a subagent swap displays mid-run if it changes its mind.

Glove.build(store?) and Glove.rebuild(store?)

The store can now be supplied at build time instead of construction time. Tools folded before build are correctly transferred into the rebuilt executor — this is what makes the subagent factory pattern work cleanly.

Pre-emptive compaction

Observer.ESCAPE_COMPACTION_THRESHOLD (default 90%) is a soft trigger before the hard CONTEXT_COMPACTION_LIMIT. If the soft threshold is crossed AND the model just produced tool calls, Agent.ask runs runCompactionNow() before appending the tool calls — keeping tool_use and matching tool_result pairs together post-summary. Configurable via the Observer constructor's 7th arg.

Message.pre_modified_text

When a hook rewrites a user message via HookResult.rewriteText, the original text is now preserved on the new pre_modified_text field of the message — so UIs can still display what the user actually typed.

Migration checklist

  1. Update every custom StoreAdapter to the new addTokens(args: TokenConsumptionCounter) signature. If you maintain a single sum, add args.tokens_in + args.tokens_out.
  2. If you wired RemoteStoreActions.addTokens for glove-react, update its signature too.
  3. Replace any defineMention call with defineSubAgent + a factory that returns a built IGloveRunnable. Remove imports of MentionContext, MentionHandler, MentionOptions, DefineMentionArgs, RegisteredMention.
  4. If you call discoveryTool directly (rather than going through mountMcp), rename to discoverySubAgent and pass it to glove.defineSubAgent(...).
  5. Update system prompts that mention find_capability — point at discovermcp via the glove_invoke_subagent dispatch tool instead.
  6. UIs reading raw user message text — be aware that slash directives now appear as [invoked_extension__<type>_<name>] placeholders. If you need the unmodified text after a hook rewrite, read Message.pre_modified_text.
  7. Optional: implement StoreAdapter.createSubAgentStore on your custom store so subagents get isolated child stores for cost attribution. Stores that don't implement it still work — the dispatcher falls back to whatever the factory builds.
  8. Optional: forward signal from Tool.run / GloveFoldArgs.do into any long-running internal work in your tools (network fetches, nested agent loops). Tools that ignore signal still get the executor's abortable-promise unwind for free.
  9. If you depend on glove-sqlite, plan a migration to a custom StoreAdapter backed by your production database. glove-sqlite still works but is no longer maintained.

Where to read more