@augmentcode/cosmos-agent-sdk-mongo
v0.0.1-alpha.0
Published
MongoDB SessionSink adapter for @augmentcode/cosmos-agent-sdk (opt-in; keeps the mongodb driver out of the core client)
Readme
@augmentcode/cosmos-agent-sdk-mongo
Opt-in MongoDB SessionSink adapter for
@augmentcode/cosmos-agent-sdk. Exports a parsed agent session
to MongoDB as typed, queryable documents (per-entry docs + a per-session
rollup) for observability and cost analysis — so a Mongo aggregation pipeline
runs directly against the collection.
Keeps the mongodb driver out of the core client per the dependency-isolation
rule (see the repo AGENTS.md):
a consumer that only uses the core client ships no mongodb. Install this
package to opt into MongoDB export.
Install
npm install @augmentcode/cosmos-agent-sdk @augmentcode/cosmos-agent-sdk-mongo mongodbUsage
The sink takes a caller-constructed mongodb client (or Db/Collection) —
it never parses a connection URL, so connection secrets stay out of the sink. It
runs the SDK's redact() on every batch before the off-box write; redaction
is not skippable (a caller may override the policy, not disable it).
import { readSession, redact } from "@augmentcode/cosmos-agent-sdk";
import { MongoSink } from "@augmentcode/cosmos-agent-sdk-mongo";
import { MongoClient } from "mongodb";
const client = new MongoClient(process.env.MONGODB_URI!);
await client.connect();
const { header, entries } = /* parseSession(...) — see below */ ({} as any);
const sink = new MongoSink({
client, // or: db / collection — a caller-supplied handle
database: "cosmos_sdk",
collectionName: "sessions",
sessionId: header.id, // read from the reader's header
});
await sink.write(entries); // redacts, then writes one doc per entry
await sink.flush(); // writes the per-session rollup doc
await client.close();Reading a session from disk (via the core reader) and streaming it live both
work — feed write() batches from readSession(...) or from watchSession(...).
Document shape
Per entry (SessionEntryDocument): sessionId, entryId, parentId,
entryType, timestamp, and — on usage-bearing entries — model
(provider/modelId), toolName, and a flat usage projection
({ input, output, cacheRead, cacheWrite, totalTokens, cost }). The full
redacted entry is preserved under entry.
Per session (SessionRollupDocument, kind: "session-rollup"): sessionId,
entryCount, totalCost, totalTokens, and perModel[]
({ model, provider, modelId, cost, tokens }).
Per-entry docs are upserted on (sessionId, entryId) and the rollup on
(kind, sessionId), so re-running the sink over a growing session is idempotent.
Spend-by-model aggregation
Because the documents are typed (not opaque blobs), a spend-by-model report is a plain aggregation over the per-entry docs:
const spend = await collection
.aggregate([
{ $match: { kind: { $exists: false }, usage: { $exists: true } } },
{
$group: {
_id: "$model",
cost: { $sum: "$usage.cost" },
tokens: { $sum: "$usage.totalTokens" },
},
},
{ $sort: { cost: -1 } },
])
.toArray();
// -> [{ _id: "anthropic/claude-sonnet-4-5", cost: 0.03, tokens: 3000 }, ...]The same totals are also available directly on the rollup document's
perModel[] — both agree by construction.
