npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tangle-network/agent-app

v0.43.51

Published

Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.

Readme

@tangle-network/agent-app

npm npm provenance license

The application-shell layer for building agent products on the Tangle stack.

The substrate packages — @tangle-network/agent-runtime, agent-eval, agent-integrations, tcloud, sandbox — are the engine. This package is the shell: the chat tool-loop, the structured agent→app side channel, the integration-hub client, per-workspace billing, field crypto, and the web boundary utilities that every agent app otherwise rewrites by hand. You supply your domain through typed seams; the package supplies the mechanism and imports none of your code.

Highlights

  • Structured tool side channelsubmit_proposal (approval-gated), schedule_followup, render_ui, add_citation, exposed as validated tool calls over three surfaces (HTTP route, per-turn MCP server, agent-runtime executor). No fenced-text parsing.
  • Bounded tool looprunAppToolLoop / streamAppToolLoop: stream a turn → collect tool calls → dispatch → fold results back → re-run, capped. Substrate-free behind a streamTurn seam, so it drives a sandboxed agent, a Worker, or an in-browser copilot unchanged.
  • Assembled chat verticalcreateChatTurnRoutes wires auth → thread/message store → streaming turn with buffered replay → uploads → sidecar question answering into one route factory, over authorize / produce / store / interactions seams. No hand-rolled orchestration. See examples/chat-app.md.
  • Sandbox-optional — the same tools, billing, eval, and loop work without a container. A fetch-only adapter maps any OpenAI-compatible stream (Tangle Router, tcloud) into the loop. See examples/browser-copilot.md.
  • Resumable turns (sandbox-free path) — for a browser/edge copilot streaming the Router directly, buffer a turn so a dropped tab loses nothing and a reconnecting client replays the tail. Sandbox products don't need this — the sandbox SDK already buffers + replays sessions (streamPrompt + lastEventId). See examples/resumable-turns.md.
  • Composes the engine, never forks it/eval re-exports @tangle-network/agent-eval's verifier; /integrations wraps the hub; /tangle and /billing take the tcloud client as a structural contract. Engines are peer dependencies — you pin the version, nothing is bundled.
  • ESM, typed, zero runtime deps in the substrate-free modules (/runtime, /web, /crypto, /redact, /stream). Ships with .d.ts and npm provenance.

Install

pnpm add @tangle-network/agent-app

The engine packages you actually use are peer dependencies — install the ones your modules touch:

# /eval composes the eval engine; /integrations composes the hub client
pnpm add @tangle-network/agent-eval @tangle-network/agent-integrations

| Peer | Required by | Range | |---|---|---| | @tangle-network/agent-eval | /eval, /eval-campaign, /profile, /knowledge | >=0.100.0 | | @tangle-network/agent-runtime | /runtime, /knowledge-loop, runtime tool execution | >=0.79.3 | | @tangle-network/agent-integrations | /integrations, /tangle | >=0.32.0 |

Modules that do not import engine packages (/tools, /web, /crypto, /redact, /stream, /billing) need no peers.

Quick start

A product supplies its taxonomy (which proposal types exist, which are approval-gated) and its handlers (the real DB/vault writes), then wires the tool side channel to whichever surface it runs on.

import {
  buildAppToolOpenAITools,
  createAppToolRuntimeExecutor,
  type AppToolHandlers,
  type AppToolTaxonomy,
} from '@tangle-network/agent-app/tools'
import { runAppToolLoop } from '@tangle-network/agent-app/runtime'

// 1. Declare the domain (the package bakes in no proposal types or rules).
const taxonomy: AppToolTaxonomy = {
  proposalTypes: ['recommend', 'contact', 'other'],
  regulatedTypes: ['recommend', 'contact'], // these require a certified approver
}

// 2. Provide the side effects — your store, your validation.
const handlers: AppToolHandlers = {
  submitProposal,
  scheduleFollowup,
  renderUi,
  addCitation,
}

// 3. Advertise the tools to the model and route their execution.
const tools = buildAppToolOpenAITools(taxonomy)
const executeToolCall = createAppToolRuntimeExecutor({
  handlers,
  taxonomy,
  ctx: { userId, workspaceId, threadId },
})

// 4. Run a bounded, tool-driven turn loop over any backend.
const result = await runAppToolLoop({
  systemPrompt,
  userMessage,
  streamTurn,                                       // wrap your model / runAgentTaskStream
  executeToolCall,
  isExecutableTool: (name) => tools.some((t) => t.function.name === name),
})

console.log(result.finalText, result.toolResults)

streamTurn is the one seam that varies by backend. For an in-browser or edge copilot talking to an OpenAI-compatible endpoint, you don't write it by hand:

import { createOpenAICompatStreamTurn, resolveTangleModelConfig } from '@tangle-network/agent-app/runtime'

const cfg = resolveTangleModelConfig() // reads provider/model/key/baseUrl from env, or pass literals
const streamTurn = createOpenAICompatStreamTurn({ ...cfg, tools })

The full three-transport walkthrough (Tangle Router, tcloud, Vercel AI SDK) is in examples/browser-copilot.md.

Building the full server chat vertical instead — auth, thread/message tables, a streaming turn with buffered replay, uploads, and sidecar question answering — is the job of createChatTurnRoutes (/chat-routes) and the modules around it. The end-to-end assembly, including the durable plan/question workflow and the client composer, is in examples/chat-app.md.

How it's organised

One rule decides where anything lives:

Does the capability make sense without a specific app's tool side channel, approval queue, or chat route? Yes → it belongs in an engine package (contribute it down). No → it's app-shell, and it belongs here.

Everything here is reached through a typed seam — AppToolHandlers, AppToolTaxonomy, streamTurn, executeToolCall, verifyToken, KeyProvisioner / WorkspaceKeyStore / KeyCrypto. The package never imports product code and never hard-codes a domain value (a proposal type, a premium, a disclaimer); each is a parameter. New capability arrives as a new subpath, never a breaking change to an existing one.

Modules

Each is an independent entry point — import only what you use.

| Subpath | What it gives you | |---|---| | /tools | The structured agent→app side channel: buildAppToolOpenAITools, createAppToolRuntimeExecutor, handleAppToolRequest (HTTP), buildAppToolMcpServer / buildHttpMcpServer (MCP), createCapabilityToken + authenticateToolRequest (capability auth), ToolInputError. | | /runtime | runAppToolLoop / streamAppToolLoop (bounded tool loop), resolveTangleModelConfig (Tangle Router / Anthropic BYOK), and toLoopEvents / createOpenAICompatStreamTurn (OpenAI-compat stream → loop events, with fragmented tool-call args reassembled). | | /integrations | Integration-hub client: HubExecClient, resolveIntegrationAction, invokeIntegrationHub. Composes @tangle-network/agent-integrations. | | /eval | producedFromToolEvents (bridge tool events into the eval verifier) and createTokenRecallChecker (deterministic content check). Re-exports @tangle-network/agent-eval's verifyCompletion, extractProducedState, weightedComposite, createLlmCorrectnessChecker. | | /tangle | App-registration consent URL (buildConsentUrl) and a cached, auto-refreshing broker-token provider (createBrokerTokenProvider). Structural over the tcloud client. | | /billing | createWorkspaceKeyManager — mint / rotate / roll over / report usage on per-workspace, budget-capped model keys. Seams for provisioner, store, and crypto. | | /crypto | AES-GCM field encryption: encryptAesGcm, decryptAesGcm, createFieldCrypto. Key supplied by the caller. | | /missions | Durable multi-step mission orchestration over a MissionStorePort seam: guarded status/step machine, idempotent plan engine with budget/approval gates, :::mission parser, the client-safe live-event reducer, and the canonical StepAgentActivity per-step delegated-run lane. | | /trace | Flow observability: buildFlowTrace + ASCII renderWaterfall/renderHistogram; the mission trace bridge (createMissionTraceContext, childSpanContext, traceEnv) whose ids/env a delegated run inherits; and delegation→FlowSpan converters (delegationActivityToFlowSpans, loopTraceEventsToFlowSpans, composeMissionFlowTrace). | | /web-react | Router-safe React chat components: ChatComposer, ModelPicker, EffortPicker, ChatMessages, RunDrillIn, plus observability surfaces — MissionActivityLane, AgentActivityPanel, FlowWaterfall. This path must not import sandbox-only UI. | | /composer | Sandbox-first AgentComposer and profile/model/sandbox-runner controls re-exported from @tangle-network/sandbox-ui/chat. Use when the chat owns a sandbox profile or needs the full sandbox composer. | | /web-react/terminal | Sandbox terminal React components, including WorkspaceTerminalPanel. Import this explicit path only for container/terminal views. | | /web | Request-boundary utilities: parseJsonObjectBody, requireString, extractRequestContext, checkRateLimit, addSecurityHeaders. | | /stream | SSE normalization and turn identity: normalizeToolEvent, resolveChatTurn, encodeEvent, message-part merging. | | /redact | redactForIngestion — PII redaction before content leaves the boundary. |

The chat vertical — the assembled server chat stack. Wire it with examples/chat-app.md.

| Subpath | What it gives you | |---|---| | /chat-routes | createChatTurnRoutes — the assembled turn vertical: NDJSON turn + buffered replay + running reconnect-discovery + composed interactions answer endpoints, over authorize / produce / store seams. Plus createSandboxChatProducer, createUploadRoute, createSandboxFileIndexRoute, withDurableChatProjection, and the import-free ./wire contract (chatTurnRequestInit, ChatTurnRequestPayload). Composes agent-runtime's handleChatTurn; subpath-only (not re-exported from the root). | | /chat-store | createChatTables + createChatStore — drizzle thread/message persistence behind the ChatStore port, and the canonical ChatMessagePart parts vocabulary (toChatMessageParts, part guards). The drizzle store/schema is subpath-only. | | /interactions | Human-in-the-loop ask channel: createInteractionAnswerRoute (list/answer endpoint factory — validation, 410 mapping, duplicate-answer safety), the server sidecar client, and the shared ChatInteraction wire/persisted-part contract + codecs. Composes @tangle-network/agent-interface types. | | /durable-chat | Durable plan/question workflow around the authoritative channels: createDurablePlanRoutes, createDurableChatScope, createDurableChatEventProjection, createDurableInteractionRoutePersistence, the DurablePlanStore port, and InMemoryDurableChatStateStore (tests/demos only — production supplies the store). | | /plans | Browser-safe durable-plan chat projection: parsePlanSubmittedEvent, planToPersistedPart / persistedPartToPlan, canTransitionPlanStatus, and the ChatPlan union. Byte-matches the SDK's SandboxSession.plan(). | | /object-store | Content-addressed durable attachment store: the ObjectStore port + createR2ObjectStore, signObjectUrl / verifyObjectUrl, createProxiedArtifactRoute, objectKey. | | /app-auth | createAppAuth — better-auth config factory + request guards (requireApiUser) over the standard users/sessions/accounts/verifications tables; composes /platform's SSO cookie minter. Optional better-auth peer; subpath-only. | | /sandbox | Workspace sandbox provisioning + turn streaming: ensureWorkspaceSandbox / peekWorkspaceSandbox, streamSandboxPrompt / runSandboxPrompt, createWorkspaceSandboxManager, and terminal / runtime-proxy handlers. Peer @tangle-network/sandbox; subpath-only. | | /platform | Tangle platform glue: cross-site SSO (createTangleSsoHandlers), request guards (createAuthGuard, guardResolution), the hub proxy, and seat billing. |

The root entry (@tangle-network/agent-app) re-exports every module, but importing the subpath keeps your bundle to what you use.

Missions: id shape and product columns

Two createMissionService seams adopters hit on day one:

  • generateId (on MissionServiceOptions) defaults to crypto.randomUUID() — a 36-char dashed UUID. If your mission table has an existing id shape (e.g. 32-hex to match D1 row defaults), inject your own generator; the service stamps it verbatim on the inserted record.
  • CreateMissionInput.extras carries opaque product-column values (a workflowId FK, a source-turn pointer) verbatim to MissionStorePort.insert(record, extras), so creation is a single write — no post-insert stamp. The service never reads them.

Compatibility

  • ESM only. Ships import + types conditions per subpath.
  • Runtimes: Node ≥ 20, Cloudflare Workers / edge, and the browser (the substrate-free modules use only Web-standard APIs — fetch, Web Crypto, TextEncoder).
  • TypeScript: strict; full .d.ts for every entry point.

Contributing

pnpm install
pnpm typecheck && pnpm test && pnpm build

Build is tsup (ESM + .d.ts), tests are vitest. A change keeps the suite green and follows the layering rule above — anything engine-general is contributed down to the substrate, not duplicated here. See AGENTS.md for the full contributor contract.

License

MIT