TRADE-OFFS · @migor/agentia
Trade-offs
This page does not list strengths. It spells out what we don't do, what those omissions cost, and when you should pick something else. The genuinely hard question when evaluating a library is never "what does it have" — it is "where does it stop, and who does the work past that line".
Positioning: the two layers it occupies
This framework deliberately occupies only two layers: the runtime (four kinds of capability + main-agent orchestration + host exports) and observability (trace / cost / metrics are first-class, not bolted on). That is the entire content of the "can it go straight to production" claim.
Every other layer — orchestrator UI, evaluation platform, memory / vector services, hosting and
deployment artifacts — is out of scope. The test is written down in the repo:
give the seam, not the policy (it appears four times in docs/spec.md).
So the answer to "should this be built in" is: anything that pulls in a third-party
dependency stays out of the core — because the core's selling point is
zero runtime dependencies (guarded by
tests/architecture/no-runtime-deps.test.ts, not a verbal promise).
⚠️ There is exactly one rule, and it is written in docs/usage-guide.md:
"does it pull in a third-party dependency", not "would users like it".
That is why the MCP stdio connector is built in (standard library only), while host
integrations such as gRPC can only ever be a recipe + example
(examples/grpc-host/ already proves "swapping the host = composing outside the seam").
When not to use it
Every row below means "this road is closed — don't pick it", not "it will get better later".
| If your situation is… | Why not pick it | Whose home turf that is |
|---|---|---|
| You want visual orchestration / low code: drag-and-drop flowcharts, editing the flow online | This framework is a library; orchestration lives in code (decorators + DI). There is no visual editor, and none is planned | LangGraph's graphs and state machines; Mastra's workflows and platform UI |
| You want Python | TypeScript only. Deno / Bun / edge runtime are unverified (outside the engines promise and outside CI) | LangGraph (Python-native), the various Python SDKs |
| You want a hosted platform (managed runs, managed memory, managed evals) | This framework ships no service. What it hands you is "a service you can deploy yourself", not the platform that runs it for you | Products that are "framework + platform" in one, such as Mastra |
| You want batteries-included vector retrieval / an eval platform | Zero runtime dependencies ⇒ no vendor SDKs installed. In src/, grep -rniE "embedding|vector|retriev" returning zero hits is deliberate | Whoever needs retrieval brings their own service (see "RAG" in the next section) |
You need client-side streaming UI bindings (React/Vue hooks like useChat) | There is no client SDK and no React binding. A server is the only shape it takes | The UI layer of the Vercel AI SDK |
| You need a 1.0-grade stability promise | Currently 0.x: minors may contain breaking changes (the rule is "it must leave a trace", not "it won't happen") | Anything that has shipped 1.0 at a size you accept |
Things deliberately left out (and who fills the gap)
| Not doing | Reason (in-repo source of truth) | How that gap gets filled |
|---|---|---|
| No vendor SDKs installed | Zero runtime dependencies is the selling point ⇒ adapters must be hand-written + global fetch | Point ANTHROPIC_BASE_URL at a compatible endpoint to switch model providers |
| No built-in logging layer / sampling / redaction / storage / deployment artifacts | docs/spec.md §9.3 locks this (stop asking for it to be "added") | The four recipes in docs/observability.md + examples/observability/ + grafana-dashboard.json |
| No built-in RAG | Not a missing feature: the shape of @Prompt is exactly "the model can call it; assets are pulled first and injected" | Replace that asset() with search(query) — zero changes in src/ |
| No built-in channel / transport layer | Same rule: anything needing a third-party client stays out of the core | examples/grpc-host/ already proves "swapping the host = composing outside the seam", and it runs in e2e |
| No client SDK / React bindings | Not in those two layers | The server returns structured results; the front end consumes them |
The three @migor/* companion packages are not published to npm | A mechanism, not an oversight: private: true — with no exceptions (tests/docs/stability.test.ts guards the set) | Copy the directory or use file:; npm i @migor/trace-view will 404, and that is a decision, not a bug |
The cost list
What you pay for choosing it, spelled out item by item (every line is verifiable yourself):
- You have to read the docs for assembly and conventions: decorators + DI are
explicit — directory conventions, provider registration,
loadEnvFile()belonging in the assembly module rather than the entry point (put it in the wrong place andagentia devsilently fails to read.env). What you get in return is "no magic"; the cost is that the first step involves reading. - You wire up the observability consumer side yourself: there is exactly one
exit (the seam
TraceSink.export(trace)), but where to store it, how to query it, whether to sample and redact is your call (the recipes are there; none of it is default behaviour). - By default the trace does not record assistant text: to get it you must turn on
traceContent:'full'explicitly, and that is priced by output bytes (measured 13.6× for large outputs, only 1.0× for small ones — see Performance order of magnitude). /healthzand/metricsare unauthenticated: in production you must restrict the reachability of/metricsat the reverse proxy (the metrics carry sensitive readings such as capability names and cost). The full list is indocs/deployment.md.- 0.x: every minor may be "this time we fixed a spot where a promise wasn't kept". The rule is that breaking changes must leave a trace (a CHANGELOG migration section) — not that there won't be any.
- Node only: the only store that touches a built-in module is
SqliteTaskStore(it needsnode:sqlitefrom Node ≥ 22.5), and it fails loudly at construction time when that is unavailable.
When to pick it
Conversely there are only three cases, and all of them are verifiable:
- You use TypeScript / Node and need to deliver a service you can deploy (not a demo).
- You treat trace / cost / metrics as first-class — they decide whether you dare to ship; they are not logs bolted on afterwards.
- You care about the install surface:
npm i @migor/agentiaadds one package and zero runtime dependencies (no vendor SDKs).
How to verify it yourself
Every claim on this page points at something checkable in the repo — don't trust this page, go run it:
- Stability promises and "which packages are not published": Versioning & stability;
tests/docs/stability.test.tsguards the wording. - The full boundary list (dozens of rows, each with a guard):
docs/usage-guide.md§7 "Known boundaries". The table on the docs page is generated at build time from the single source, so it cannot drift. - Performance order of magnitude and the re-run commands: Performance order of magnitude (⚠️ milliseconds are local-machine figures, not an SLA).
- Deployment checklist:
docs/deployment.md. - Zero dependencies itself:
tests/architecture/no-runtime-deps.test.ts.