{"_id":"@diagrid/agent-mastra","_rev":"4-c32b9df3a257a429ff03c4ec423cddf7","name":"@diagrid/agent-mastra","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@diagrid/agent-mastra","version":"0.1.0","keywords":["dapr","workflow","durable","mastra","ai","agents","diagrid"],"author":{"name":"Diagrid Inc."},"license":"BUSL-1.1","_id":"@diagrid/agent-mastra@0.1.0","maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"homepage":"https://github.com/diagridio/typescript-ai/tree/main/packages/mastra#readme","bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"dist":{"shasum":"abc0d35a55543e508248c63ad6e90d9d6a655a14","tarball":"https://registry.npmjs.org/@diagrid/agent-mastra/-/agent-mastra-0.1.0.tgz","fileCount":9,"integrity":"sha512-znb6fdVZroDUs6A9gvdPRvqjN10sjQQCKJxxQAFLJwZtb9lHqADNPP6VdAJqDNb/+J67kdFjP90kDS3YPKNkTw==","signatures":[{"sig":"MEUCIA9VM4kHuKtmRtoTp883fck2EhkKxiQCu18M0hGOiu+XAiEA2mmQorb6D8+S4U8xkp2gOuea3JFXCzVAh7bibJwmQgI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":225939},"main":"./dist/index.cjs","type":"module","_from":"file:/private/tmp/claude-501/-Users-caspernielsen-workspace-catalyst-ai/329d1331-b5e1-4ec9-a50f-ae4d7c35beaf/scratchpad/npm-packs/diagrid-agent-mastra-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"scripts":{"build":"tsup","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""},"_npmUser":{"name":"casperwmn","email":"whopsec@protonmail.com"},"_resolved":"/private/tmp/claude-501/-Users-caspernielsen-workspace-catalyst-ai/329d1331-b5e1-4ec9-a50f-ae4d7c35beaf/scratchpad/npm-packs/diagrid-agent-mastra-0.1.0.tgz","_integrity":"sha512-znb6fdVZroDUs6A9gvdPRvqjN10sjQQCKJxxQAFLJwZtb9lHqADNPP6VdAJqDNb/+J67kdFjP90kDS3YPKNkTw==","repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/mastra"},"_npmVersion":"11.6.2","description":"Durable execution of Mastra agents on Dapr Workflows","directories":{},"sideEffects":false,"_nodeVersion":"24.11.1","dependencies":{"@diagrid/agent-core":"0.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"zod":"4.4.3","tsup":"8.5.1","typescript":"6.0.3","@mastra/core":"1.57.0"},"peerDependencies":{"zod":"^4.0.0","@mastra/core":">=1.50.0 <2"},"_npmOperationalInternal":{"tmp":"tmp/agent-mastra_0.1.0_1787475177063_0.41862419637069515","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@diagrid/agent-mastra","version":"0.1.1","keywords":["dapr","workflow","durable","mastra","ai","agents","diagrid"],"author":{"name":"Diagrid Inc."},"license":"BUSL-1.1","_id":"@diagrid/agent-mastra@0.1.1","maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"homepage":"https://github.com/diagridio/typescript-ai/tree/main/packages/mastra#readme","bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"dist":{"shasum":"131286d6a183b94802002cff9c4752b57afe4223","tarball":"https://registry.npmjs.org/@diagrid/agent-mastra/-/agent-mastra-0.1.1.tgz","fileCount":9,"integrity":"sha512-aCY2NRNWLwK/ULRwEzLGI4zuHak9zHNnEwm7CjW0zbCUkK3E2MPFmjYHwEYA0TUxRdjX8nhOkShe9k9DaQC1uA==","signatures":[{"sig":"MEUCIG1mamLrTlK8b6EPf7npYMTLGQSb5JxLG6wSCHg6FYHqAiEAxBflE0IawyDI0DDlFaODkGv3G+GuzczLR+kC934tpUk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDBkvdiIgdzNbqFkrzofUz2V5tu15apOrHTvWY66X+4NAIgatP+umYgn3RkgKzlGcrYjfk0hAC9zdUmqsfEWaWLm5k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diagrid%2fagent-mastra@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":238675},"main":"./dist/index.cjs","type":"module","_from":"file:dist-packs/diagrid-agent-mastra-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.13.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"scripts":{"build":"tsup","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:0d410872-4f9f-4380-ad4d-8b80d2e9be11"}},"_resolved":"/home/runner/work/typescript-ai/typescript-ai/dist-packs/diagrid-agent-mastra-0.1.1.tgz","_integrity":"sha512-aCY2NRNWLwK/ULRwEzLGI4zuHak9zHNnEwm7CjW0zbCUkK3E2MPFmjYHwEYA0TUxRdjX8nhOkShe9k9DaQC1uA==","repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/mastra"},"_npmVersion":"11.19.0","description":"Durable execution of Mastra agents on Dapr Workflows","directories":{},"sideEffects":false,"_nodeVersion":"24.20.0","dependencies":{"@diagrid/agent-core":"0.1.1"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"zod":"4.4.3","tsup":"8.5.1","typescript":"6.0.3","@mastra/core":"1.57.0"},"peerDependencies":{"zod":"^4.0.0","@mastra/core":">=1.50.0 <2"},"_npmOperationalInternal":{"tmp":"tmp/agent-mastra_0.1.1_1789669443632_0.5059558645402265","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@diagrid/agent-mastra@0.2.0","bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"dist":{"shasum":"a5d988f59a8ba15f1a8752d31601e82da5122e2a","tarball":"https://registry.npmjs.org/@diagrid/agent-mastra/-/agent-mastra-0.2.0.tgz","fileCount":9,"integrity":"sha512-1ebIHPJ9s5RGamAyDmTtKt32FW5NVmLljkKqNCDppvpjJhsoC94ONMZYYEaJR2wqGLgdmpu3wo2lYBO3aNVTFg==","signatures":[{"sig":"MEUCIQDwsb7hCfMugJmPqwkGjmKWl0wmjaJu9ros56kXbN+8/QIgRS4a38BEdsX5l2EqJUXjziPB8IgzmKiVA+eJS7zJtac=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDE8s8i60AWqudvCntgV0XjdBkYdSprM/5jk2zJu9IilgIhAKFz5juhNHb0kGWUDiOdUWvpDJ+u0UBBMQ620c8hb/o6"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diagrid%2fagent-mastra@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":238675},"main":"./dist/index.cjs","name":"@diagrid/agent-mastra","type":"module","_from":"file:dist-packs/diagrid-agent-mastra-0.2.0.tgz","types":"./dist/index.d.ts","author":{"name":"Diagrid Inc."},"module":"./dist/index.js","engines":{"node":">=22.13.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./package.json":"./package.json"},"license":"BUSL-1.1","scripts":{"build":"tsup","clean":"node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""},"version":"0.2.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:0d410872-4f9f-4380-ad4d-8b80d2e9be11"}},"homepage":"https://github.com/diagridio/typescript-ai/tree/main/packages/mastra#readme","keywords":["dapr","workflow","durable","mastra","ai","agents","diagrid"],"_resolved":"/home/runner/work/typescript-ai/typescript-ai/dist-packs/diagrid-agent-mastra-0.2.0.tgz","_integrity":"sha512-1ebIHPJ9s5RGamAyDmTtKt32FW5NVmLljkKqNCDppvpjJhsoC94ONMZYYEaJR2wqGLgdmpu3wo2lYBO3aNVTFg==","repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/mastra"},"_npmVersion":"11.19.0","description":"Durable execution of Mastra agents on Dapr Workflows","directories":{},"maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"sideEffects":false,"_nodeVersion":"24.20.0","dependencies":{"@diagrid/agent-core":"0.2.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"zod":"4.4.3","tsup":"8.5.1","typescript":"6.0.3","@mastra/core":"1.57.0"},"peerDependencies":{"zod":"^4.0.0","@mastra/core":">=1.50.0 <2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-mastra_0.2.0_1789684448415_0.03577845334435037"}}},"time":{"created":"2026-08-23T08:52:56.868Z","modified":"2026-09-17T22:34:08.890Z","0.1.0":"2026-08-23T08:52:57.183Z","0.1.1":"2026-09-17T18:24:03.702Z","0.2.0":"2026-09-17T22:34:08.534Z"},"bugs":{"url":"https://github.com/diagridio/typescript-ai/issues"},"author":{"name":"Diagrid Inc."},"license":"BUSL-1.1","homepage":"https://github.com/diagridio/typescript-ai/tree/main/packages/mastra#readme","keywords":["dapr","workflow","durable","mastra","ai","agents","diagrid"],"repository":{"url":"git+https://github.com/diagridio/typescript-ai.git","type":"git","directory":"packages/mastra"},"description":"Durable execution of Mastra agents on Dapr Workflows","maintainers":[{"name":"casperwmn","email":"whopsec@protonmail.com"}],"readme":"# @diagrid/agent-mastra\n\nDurable execution of [Mastra](https://mastra.ai) agents on\n[Dapr Workflows](https://docs.dapr.io/developing-applications/building-blocks/workflow/).\n\nThe agent's control loop is modelled as a Dapr Workflow and each model call and\ntool execution as a durable activity, so an agent survives process crashes,\nsidecar restarts and provider outages without re-running work it already\ncompleted.\n\n## Status\n\nWorking, and verified by running it rather than by inspection — against a local\n`dapr run` sidecar and against Diagrid Catalyst, with Ollama (`qwen2.5:7b`) as the\nmodel.\n\n| Area                                       | State                                                                |\n| ------------------------------------------ | -------------------------------------------------------------------- |\n| Runner lifecycle and workflow naming       | ✅                                                                   |\n| Durable agent loop (`agentWorkflow`)       | ✅ model call → tool activities → repeat                             |\n| Model bridge                               | ✅ one step per iteration via `clientTools`                          |\n| Tool bridge                                | ✅ one checkpointed activity per tool call                           |\n| Crash recovery                             | ✅ tool not re-run after a mid-turn kill (see at-least-once below)   |\n| Activity retry (model and tool)            | ✅ in-orchestrator, 3 attempts with durable backoff                  |\n| Registry metadata (`getMetadata()`)        | ⚠️ the record is correct, but nothing publishes it — see below       |\n| Checkpoint persistence                     | ⚠️ implemented and tested, but the runner never calls it — see below |\n| Native Dapr activity `RetryPolicy`         | ❌ not in the JS SDK; the orchestrator retries instead               |\n| Component discovery for registry metadata  | ❌ `TODO(mastra-adapter)`                                            |\n| Tools needing `RequestContext` / workspace | ❌ `TODO(mastra-adapter)`                                            |\n\n### The two ⚠️ rows\n\nBoth are built and unit-tested but have no caller — a working part is not the\nsame thing as a working feature:\n\n- **Checkpoint persistence.** `DaprMastraCheckpointer.save()/load()/list()` have\n  no callers outside their tests. The runner constructs one and exposes it as a\n  public field; nothing writes to it, so `load()` always returns `undefined` in\n  practice. Continuing a thread today means passing prior `messages` into\n  `invoke()` yourself.\n- **Registry metadata.** `getMetadata()` returns a _mostly_ correct record — the\n  examples print it — but nothing publishes it to a state store or agent\n  registry, and three of its fields are not configuration. `memory.shortTerm`\n  reports `{ type: 'DaprMastraCheckpointer' }`, accurate about intent and ahead\n  of the wiring. `agent.maxIterations` is hardcoded to `1` and `pubsub` is\n  `{ resourceName: '', broadcastTopic: null, agentTopic: null }` — both\n  `TODO(mastra-adapter)` in `mapper.ts`. Read those three as unset rather than\n  as settings: `inspect-agent.ts` builds its runner with `maxIterations: 10` and\n  will still print `1`.\n\n`grep -rn 'TODO(mastra-adapter)' .` from the repo root lists what is left — six\nmarkers. Scoping it to `src` from this directory finds only three; the other\nthree moved into `packages/core` with the durable loop. `tests/e2e/` runs the\nexamples under a real sidecar in CI, so these claims stay honest.\n\n## Install\n\n```bash\npnpm add @diagrid/agent-mastra @mastra/core zod\n```\n\n`@mastra/core` and `zod` are **peer** dependencies: your application owns their\nversions, and installing this adapter never pulls another framework's SDK into\nyour tree. Both have to be named on the install line — a peer dependency is not\ninstalled for you.\n\n- Node.js ≥ 22.13\n- `@mastra/core` ≥ 1.50 < 2\n- `zod` ^4\n\n## Usage\n\n```ts\nimport { Agent } from '@mastra/core/agent';\nimport { openai } from '@ai-sdk/openai';\nimport { DaprWorkflowAgentRunner } from '@diagrid/agent-mastra';\n\nconst agent = new Agent({\n  id: 'support-agent',\n  name: 'support-agent',\n  instructions: 'You help customers with billing questions.',\n  model: openai('gpt-4o-mini'),\n});\n\nconst runner = new DaprWorkflowAgentRunner({\n  agent,\n  name: 'support-agent',\n  maxIterations: 10,\n});\n\n// Shut down cleanly on SIGINT/SIGTERM (opt-in: a library must not install\n// process-wide handlers behind your back).\nconst disposeHandlers = runner.registerShutdownHandlers();\n\nawait runner.start();\n\nconst result = await runner.invoke({\n  prompt: 'Why was I charged twice?',\n  threadId: 'thread-123',\n});\n\nconsole.log(result.text, result.status, result.iterations);\n\ndisposeHandlers();\nawait runner.shutdown();\n```\n\nPrefer `runner.schedule(...)` when the caller should not block — an agent turn\noutliving an HTTP request is the normal case, not the exception. It returns the\nworkflow instance id, which you can poll with `runner.getWorkflowStatus(id)`.\n\n## Module layout\n\nThe same shape every adapter in this repo follows:\n\n| File         | Role                                                                     |\n| ------------ | ------------------------------------------------------------------------ |\n| `bridge.ts`  | Drives Mastra one step at a time — the only file that knows Mastra's API |\n| `mapper.ts`  | `MastraAgentMapper` — the `BaseAgentMapper` implementation               |\n| `runner.ts`  | Public entrypoint — `DaprWorkflowAgentRunner`, lifecycle and invocation  |\n| `state.ts`   | `DaprMastraCheckpointer` — core's checkpointer with the `mastra` prefix  |\n| `version.ts` | Version marker, stamped by the release workflow                          |\n\nThe durable agent loop is **not** here. The orchestrator, its activities, the\nretry behaviour and the I/O schemas live in `@diagrid/agent-core` under\n`src/agent/`, and this package re-exports them so importing the adapter is still\nenough to work with a turn. They moved there because none of them mentioned\nMastra: leaving them in an adapter meant adapter #2 would copy the durable loop\nand the cross-language checkpoint key layout, subtle invariants included, and the\ntwo would drift.\n\n## Notes on metadata extraction\n\n`MastraAgentMapper` reads a Mastra `Agent` **structurally** rather than\nimporting `@mastra/core`. That is deliberate: importing the framework here would\nput it in the runtime graph of anyone installing the adapter, which\n`tests/guards/cross-framework-imports.test.ts` forbids.\n\nFour consequences worth knowing:\n\n- **Config is read through the class accessors**, not the plain properties. A\n  real `Agent` keeps `instructions` and `tools` private and exposes them via\n  `getInstructions()` and `listTools()`; reading `agent.tools` returns\n  `undefined`. `listTools()` is async, which is why\n  `mapper.mapAgentMetadata()` and `runner.getMetadata()` are async too.\n- **All three of Mastra's model forms are supported**: the model-router magic\n  string (`'openai/gpt-4o-mini'`), an OpenAI-compatible config\n  (`{ id, url }` or `{ providerId, modelId, url }` — how you point at Ollama),\n  and an AI SDK model instance. A malformed router id is echoed back verbatim so\n  the typo is visible in the registry, rather than collapsed to `unknown`.\n- Mastra also accepts `instructions`, `model` and `tools` as a **factory**. A\n  factory needs a `RuntimeContext` that does not exist at registration time, so\n  dynamic config is **skipped** — the registry shows the static configuration. It\n  does not guess.\n- Tool argument schemas are rendered as JSON Schema via Zod 4's\n  `z.toJSONSchema()`. Zod 3 schemas and schemas containing transforms are not\n  representable, and degrade to an empty string rather than to\n  `[object Object]`.\n\nSee [`examples/mastra/`](../../examples/mastra/README.md) — `pnpm inspect` prints\nthe whole record for a real agent.\n\n## License\n\n[Business Source License 1.1](../../LICENSE.md) — © 2026–Present Diagrid Inc.\n\n## At-least-once, not exactly-once\n\nThe workflow engine guarantees that each activity runs **at least once**. Any\nactivity with a side effect must therefore be safe to run twice.\n\nThe activity boundary makes a completed call durable: once its result is\ncheckpointed, replay reads the checkpoint rather than calling out again. But\nthere is a window between an activity function returning and the engine durably\nrecording that completion, and a crash inside that window re-runs the activity.\nFor `invokeModel` that means the model is called — and billed — twice. For a tool\nit means whatever the tool does happens twice.\n\nSo a tool that charges a card, sends an email, or writes a non-idempotent record\nneeds its own idempotency key or conditional write. The engine narrows the window\nand cannot close it.\n\nThe crash-recovery example demonstrates one specific kill timing where the tool is\nnot re-run. It does not, and structurally cannot, demonstrate the absence of this\nwindow.\n","readmeFilename":"README.md"}