Skip to content

feat(birmel): replace VoltAgent with explicit AI SDK runtime - #2009

Open
shepherdjerred wants to merge 6 commits into
mainfrom
inspect-birmel-project
Open

feat(birmel): replace VoltAgent with explicit AI SDK runtime#2009
shepherdjerred wants to merge 6 commits into
mainfrom
inspect-birmel-project

Conversation

@shepherdjerred

@shepherdjerred shepherdjerred commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace VoltAgent and hidden framework memory with one explicit AI SDK 6 runtime: admission and deduplication, bounded context, typed routing, exactly one direct or specialist agent, one edited Discord response, then typed claim extraction.
  • Preserve the elected persona, trusted-user authority boundary, stable tool IDs, all tool domains, ordered turns, thread sessions, and durable scheduled work.
  • Add deterministic claim memory with revisions, just-in-time Glitter friend context, real thread-bound sessions, atomic AgentJob execution, strict configuration, content-free telemetry, and liveness/readiness endpoints.
  • Replace startup db push with a verified baseline plus additive Prisma migration while leaving mastra-memory.db disconnected and untouched.

Verification

  • Birmel focused Turbo graph: 7 of 7 tasks passed; 252 tests passed, 0 failed, 0 skipped.
  • Glitter context: 16 tests passed.
  • Birmel deployment manifests: 2 tests passed.
  • Fresh and production-shaped migration fixtures passed, including fingerprint rejection and no assembled-prompt persistence.
  • Latest Docker image built and passed the in-container startup/dependency smoke.
  • Docs checker validated all 621 documents; changed Markdown passed markdownlint.
  • Staged-file hooks passed Gitleaks, Prettier, lockfile, suppression, line-ending, merge-marker, environment-name, and size checks.

Deployment boundary

This remains draft until Buildkite is green. Immediately before production rollout: recheck legacy/runtime row counts, record the current image and environment, create and verify a fresh PVC snapshot, then deploy through the existing image and GitOps flow. Live acceptance must cover conversation, read/write tools, memory lifecycle, a two-turn thread session, a one-shot job, browser/editor health, one reply per input, clean logs/traces, stable context sizes, and no writes to mastra-memory.db.

@shepherdjerred

Copy link
Copy Markdown
Owner Author

This change is part of the following stack:

Change managed by git-spice.

@shepherdjerred

Copy link
Copy Markdown
Owner Author

@codex review

@shepherdjerred
shepherdjerred marked this pull request as ready for review August 8, 2026 11:01
@qodo-code-review

qodo-code-review Bot commented Aug 8, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Timeout releases job lease ✓ Resolved 🐞 Bug ☼ Reliability
Description
When an agent job times out, the timeout wrapper does not cancel the underlying execution, but
failure handling clears the job lease (claimedBy/leaseExpiresAt), allowing the same job to be
re-claimed and executed again while the first execution may still be performing side effects (tool
execution / Discord delivery). This can produce duplicate messages or repeated tool actions for a
single scheduled run.
Code

packages/birmel/src/scheduler/jobs/agent-jobs.ts[R125-127]

+        claimedAt: null,
+        claimedBy: null,
+        leaseExpiresAt: null,
Evidence
withAgentJobTimeout uses Promise.race (no cancellation), while markJobFailure clears the lease
fields that gate claiming. Because durable execution can send Discord messages or execute tools, a
reclaim can duplicate side effects.

packages/birmel/src/scheduler/agent-job-schedule.ts[174-190]
packages/birmel/src/scheduler/jobs/agent-jobs.ts[91-129]
packages/birmel/src/scheduler/jobs/agent-jobs.ts[165-209]
packages/birmel/src/scheduler/jobs/scheduled-tasks.ts[272-287]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Agent jobs are timed out via `Promise.race`, which does **not** stop the underlying `executeDurableAgentJob` work. On timeout, the code immediately clears `claimedBy`/`leaseExpiresAt`, making the job eligible for re-claim/retry while the original execution may still be running and causing side effects (Discord sends, tool writes).

## Issue Context
- Timeouts are currently used as a control-flow mechanism, not a cancellation mechanism.
- Durable jobs can perform external side effects (Discord delivery) and invoke tools.

## Fix Focus Areas
- packages/birmel/src/scheduler/agent-job-schedule.ts[174-191]
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[91-131]
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[165-210]
- packages/birmel/src/scheduler/jobs/scheduled-tasks.ts[272-287]

## Implementation direction
Choose one of these safe approaches:
1) **Abortable execution**: Change `withAgentJobTimeout` to use an `AbortController` and pass an `AbortSignal` down into `executeDurableAgentJob` and any tool/agent/Discord operations so they can stop promptly. Only clear the lease after the operation settles (or is confirmed aborted).
2) **Lease fencing on timeout** (no cancellation): If the failure is a timeout, do **not** clear `claimedBy`/`leaseExpiresAt` in `markJobFailure`. Keep the job in `running` until the lease naturally expires, and let `recoverExpiredJobLeases()` transition it to `retrying`/`recovered`.
3) **Idempotency key fencing**: Introduce an execution/run id that tools and delivery paths must include and enforce idempotency (e.g., “at-most-once delivery” keyed by job run id), and keep the lease until completion.

Add/adjust tests to cover: timeout -> underlying work continues -> job should not be immediately reclaimable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Burst agent-job concurrency ✓ Resolved 🐞 Bug ➹ Performance
Description
The scheduler now executes all due agent jobs in parallel (up to 25 at once) via Promise.allSettled
without a concurrency limiter, which can spike resource usage and outbound calls. This increases the
likelihood of rate limits and operational instability when jobs involve model calls, browser
automation, or Discord actions.
Code

packages/birmel/src/scheduler/jobs/agent-jobs.ts[R302-304]

+  const results = await Promise.allSettled(
+    dueJobs.map((job) => trackJobExecution(processAgentJob(job))),
+  );
Evidence
The code explicitly selects up to 25 due jobs and executes them via Promise.allSettled over the
mapped job processors, which starts them concurrently with no additional throttling.

packages/birmel/src/scheduler/jobs/agent-jobs.ts[286-304]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`runAgentJobsTick` launches all due jobs concurrently (bounded only by `take: 25`) using `Promise.allSettled(dueJobs.map(processAgentJob))`. This creates bursty load and can overwhelm shared resources or external dependencies.

## Issue Context
Each `processAgentJob` can execute tools and/or Discord delivery, and may involve expensive work. Even with a batch limit of 25, running all 25 simultaneously can be too aggressive depending on deployment size and provider limits.

## Fix Focus Areas
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[286-311]

## Implementation direction
- Introduce a concurrency limiter (e.g., a simple semaphore or `p-limit`) and run jobs with `maxConcurrentAgentJobs` from config.
- Keep `take: 25` as a fetch batch size, but process in chunks respecting the concurrency limit.
- Optionally add jitter/backoff when many jobs are due simultaneously.

Add tests or assertions ensuring no more than N jobs are started concurrently per tick.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Edited ## Comment Log entry ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
A previously existing ## Comment Log entry was modified instead of only appending new entries.
This violates the append-only requirement for comment logs and can compromise auditability of change
history.
Code

packages/docs/todos/birmel-tests-polish.md[R52-55]

+### 2026-08-08 — Birmel 3.0 implementation

-- Retained as active. The repository still has broad unit coverage and several
-  component e2e scripts, but no committed deterministic message-to-tool
-  delegation test or recorded full Discord happy-path proof.
+- Replaced the stale VoltAgent-era testing inventory with the current explicit
+  runtime contract. Automated coverage is complete; only direct production
Evidence
PR Compliance ID 2598594 requires ## Comment Log sections to be append-only; existing lines must
not be changed or removed. The change replaces the prior dated entry rather than appending a new one
to the end of the section.

Rule 2598594: Comment log sections must be append-only
packages/docs/todos/birmel-tests-polish.md[50-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`## Comment Log` sections must be append-only, but the PR edits/replaces an existing log entry instead of adding a new entry at the end.

## Issue Context
Comment logs are treated as an audit trail; modifying prior entries breaks that guarantee.

## Fix Focus Areas
- packages/docs/todos/birmel-tests-polish.md[50-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Checked tasks under ## Remaining ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The plan uses pre-checked task items (- [x]) under ## Remaining, but the rule requires agent
work items to be represented as unchecked Markdown tasks (- [ ]). This breaks the standardized
format for tracking remaining work.
Code

packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md[R180-183]

+- [x] Mirror the approved contracts in code and add the baseline/additive
+      schema migrations.
+- [x] Replace VoltAgent orchestration, memory, and tool adaptation with the
+      explicit AI SDK runtime.
Evidence
PR Compliance ID 2598586 requires that agent work items under a ## Remaining heading be
represented as unchecked tasks (- [ ]) and explicitly disallows pre-checked items. The plan
currently includes multiple - [x] entries under ## Remaining.

Rule 2598586: Represent agent work items as unchecked Markdown tasks under a ## Remaining heading
packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md[178-193]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`## Remaining` contains pre-checked tasks (`- [x]`), but remaining agent work items must be unchecked (`- [ ]`).

## Issue Context
This plan is tracked as a board item and should follow the standardized remaining-work format.

## Fix Focus Areas
- packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md[178-196]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 66 rules

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md Outdated
Comment thread packages/docs/todos/birmel-tests-polish.md
Comment thread packages/birmel/src/scheduler/jobs/agent-jobs.ts
Comment thread packages/birmel/src/scheduler/jobs/agent-jobs.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f11538cb9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +191 to +193
CASE WHEN "toolId" IS NULL THEN 'message' ELSE 'tool' END,
CASE WHEN "toolId" IS NULL THEN "naturalDesc" ELSE NULL END,
"toolId", "toolInput", 'discord', 3, 300000,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Convert legacy send-message rows into message jobs

When production contains a pending ScheduledTask whose toolId is send-message, this migration classifies it as a tool payload and preserves that obsolete ID. The previous migration helper explicitly converted these rows into message payloads, while the new registry contains manage-message but no send-message, so the migrated reminder will retry and eventually fail instead of being delivered. Extract the stored content and migrate this case as payloadKind = 'message' before dropping ScheduledTask.

AGENTS.md reference: packages/birmel/AGENTS.md:L34-L35

Useful? React with 👍 / 👎.

Comment on lines +37 to +38
"manage-scheduled-message",
metadata("manage-scheduled-message", "messaging", "write"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Route scheduled messages through manage-job

Registering manage-scheduled-message keeps the legacy ScheduledAnnouncement scheduler exposed alongside the new durable job runtime. Requests routed to messaging can therefore create delayed work that bypasses AgentJob claims, run history, request-context persistence, and retry behavior, despite the package contract designating manage-job as the sole jobs surface. Remove this registration or implement scheduled messages as manage-job message payloads.

AGENTS.md reference: packages/birmel/AGENTS.md:L68-L71

Useful? React with 👍 / 👎.

Comment on lines +208 to +209
const job = await prisma.agentJob.create({
data: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce configured job limits before insertion

When repeated create requests reach SCHEDULER_MAX_TASKS_PER_GUILD (or the recurring-job cap), this path still inserts every job because neither configured scheduler limit is consulted anywhere in the new creation flow. The replaced scheduling surface rejected creation at the guild cap; losing that guard allows an agent or trusted user to grow the durable queue without bound and increases every scheduler scan. Count the applicable active/recurring jobs and reject creation at the configured limits, ideally in the same transaction as the insert.

Useful? React with 👍 / 👎.

@qodo-code-review

qodo-code-review Bot commented Aug 8, 2026

Copy link
Copy Markdown

PR Summary by Qodo

feat(birmel): replace VoltAgent with explicit AI SDK 6 agent runtime

✨ Enhancement ⚙️ Configuration changes 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Replace VoltAgent and its hidden framework memory with an explicit AI SDK 6 pipeline:
 admission/dedup, bounded context assembly, typed routing, single direct/specialist agent execution,
 one edited Discord reply, then typed claim extraction.
• Introduce deterministic claim-based memory (MemoryClaim/MemoryRevision), thread-bound AgentSession
 runtime, atomic AgentJob execution, and a new Glitter friend-context package for just-in-time lore.
• Add liveness/readiness health endpoints, stricter zod-validated configuration, content-free
 telemetry, and a verified-baseline Prisma migration flow replacing db push.
• Remove the entire legacy voltagent/ module (agents, memory, message handler/stream, conversation
 lock, sanitize) and related timers/message-builder tooling now superseded by the new runtime.
• Large accompanying test suite covering admission, context bundling, migrations, durable jobs,
 memory, sessions, router, tools, and health checks.
Diagram

graph TD
  A["Discord messageCreate"] --> B["Admission + Session Check"] --> C["AgentRun (dedup)"] --> D["Turn Context Builder"]
  D --> E[(Memory Claims)]
  D --> F[[Glitter Friend Context]]
  D --> G["Router (typed)"]
  G --> H{{"Direct or Specialist Agent"}}
  H --> I["Discord Reply (single edit)"]
  I --> J["Memory Extraction"] --> E
  H --> K[(AgentJob / Scheduler)]
  K --> L[(Prisma / SQLite)]
  D --> L
  subgraph Legend
    direction LR
    _db[(Database)] ~~~ _svc([Process Step]) ~~~ _dec{{Decision/Agent}} ~~~ _ext[[External Package]]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Incremental strangler-fig migration (keep VoltAgent, migrate one specialist at a time)
  • ➕ Lower risk per deploy
  • ➕ Easier bisection if regressions appear
  • ➕ Allows production soak time between changes
  • ➖ Requires running two parallel memory/runtime systems temporarily
  • ➖ Slower to reach the simplified explicit-context goal
  • ➖ More total engineering overhead maintaining a bridge layer
2. Keep VoltAgent but bypass its hidden memory with custom context injection
  • ➕ Smaller diff, retains framework's built-in agent orchestration
  • ➖ Still opaque tool-loop internals and versioning risk
  • ➖ Does not solve the stable-tool-ID and deterministic-context goals as cleanly
  • ➖ Framework upgrades remain a recurring risk (as evidenced by the archived voltagent-ai-sdk-7-upgrade doc)

Recommendation: Replacing a hidden-memory agent framework with an explicit, typed, schema-validated pipeline is the right call for an auditable, safety-critical Discord bot: it makes context assembly, routing, and memory writes inspectable and testable, and the verified-baseline + additive-migration strategy safely preserves production data instead of risking db push drift. The main residual risk is the size of the single PR (full framework swap + schema overhaul + new package) — splitting deployment into schema/migration first, then runtime swap, would have reduced blast radius, but the extensive test suite and staged rollout plan mitigate this.

Files changed (111) +12123 / -3946

Enhancement (14) +1505 / -1074
agent-job-actions.tsUpdate job tool actions to new AgentJob/session model +331/-258

Update job tool actions to new AgentJob/session model

• Refactors job create/update/cancel/list actions to use actor authority, session binding, and leasing-related fields.

packages/birmel/src/agent-tools/tools/automation/agent-job-actions.ts

agent-jobs.tsAlign automation job tool with new execution semantics +94/-57

Align automation job tool with new execution semantics

• Updates AgentJob tool wiring for the new runtime/job execution APIs.

packages/birmel/src/agent-tools/tools/automation/agent-jobs.ts

messages.tsUpdate Discord message tooling for single-reply runtime ownership +4/-2

Update Discord message tooling for single-reply runtime ownership

• Tweaks Discord messaging tools to align with the runtime owning the single source-channel reply (placeholder + edit).

packages/birmel/src/agent-tools/tools/discord/messages.ts

scheduling.tsUpdate scheduling tools for new job/session model +14/-9

Update scheduling tools for new job/session model

• Refactors scheduling-related tool code to align with AgentJob execution and updated schema.

packages/birmel/src/agent-tools/tools/discord/scheduling.ts

index.tsRework manage-memory tool for claim-based memory +227/-160

Rework manage-memory tool for claim-based memory

• Updates memory tooling to operate on MemoryClaim/MemoryRevision rather than legacy free-form memory rows.

packages/birmel/src/agent-tools/tools/memory/index.ts

request-context.tsAdd helper to run tool/agent execution with request context +2/-0

Add helper to run tool/agent execution with request context

• Introduces utilities for capturing/restoring trusted request context used by the runtime and job executor.

packages/birmel/src/agent-tools/tools/request-context.ts

index.tsRebuild session tools for thread-bound sessions +100/-216

Rebuild session tools for thread-bound sessions

• Refactors session management to create and operate on real Discord-thread-backed AgentSessions and sequenced events.

packages/birmel/src/agent-tools/tools/sessions/index.ts

channel-history.tsUpdate transcript retrieval helpers for new context builder +22/-14

Update transcript retrieval helpers for new context builder

• Adjusts transcript windowing/return types to support ContextBundle construction and post-turn memory extraction.

packages/birmel/src/discord/utils/channel-history.ts

index.tsSwitch startup to Birmel 3 runtime + health server +38/-41

Switch startup to Birmel 3 runtime + health server

• Wires in the new runtime message handler, configures job agent execution dependencies, starts health endpoints, and makes shutdown idempotent with exit codes.

packages/birmel/src/index.ts

index.tsExpose scheduler started state and update lifecycle +115/-32

Expose scheduler started state and update lifecycle

• Adds isSchedulerStarted (used by readiness) and restructures scheduler startup/shutdown integration.

packages/birmel/src/scheduler/index.ts

agent-jobs.tsRefactor durable agent job runner for new schema/runtime +260/-279

Refactor durable agent job runner for new schema/runtime

• Updates durable job execution logic to the new AgentJob fields (actor/session/lease) and runtime dependency injection.

packages/birmel/src/scheduler/jobs/agent-jobs.ts

announcements.tsKeep announcements job compatible with new scheduler boot +6/-0

Keep announcements job compatible with new scheduler boot

• Small adjustments ensuring announcement scheduling remains intact under the updated scheduler wiring.

packages/birmel/src/scheduler/jobs/announcements.ts

scheduled-tasks.tsRewrite scheduled tasks to execute tools/agents with strict context and logging +290/-6

Rewrite scheduled tasks to execute tools/agents with strict context and logging

• Introduces AgentJobExecution descriptor, pluggable runtime dependencies, trusted actor checks, session event logging, and delivery abstraction for Discord.

packages/birmel/src/scheduler/jobs/scheduled-tasks.ts

image.tsSupport attachment extraction for new TurnInput +2/-0

Support attachment extraction for new TurnInput

• Minor enhancement to image attachment extraction used by the typed TurnInput pipeline.

packages/birmel/src/utils/image.ts

Bug fix (1) +11 / -5
DockerfileBake Prisma engines into the runtime image +11/-5

Bake Prisma engines into the runtime image

• Ensures Prisma query engines are present in the container image to prevent runtime failures in production-like environments.

packages/birmel/Dockerfile

Refactor (26) +134 / -1694
provider-options.tsCentralize OpenAI provider options +35/-0

Centralize OpenAI provider options

• Provides consistent provider options (e.g., reasoning effort/verbosity) for AI SDK calls.

packages/birmel/src/agent-runtime/provider-options.ts

browser.tsMinor update for new tool wrapper expectations +1/-1

Minor update for new tool wrapper expectations

• Aligns browser automation tool with the new tool factory/metadata requirements.

packages/birmel/src/agent-tools/tools/automation/browser.ts

index.tsUpdate automation tool exports +2/-4

Update automation tool exports

• Adjusts exports to match the updated tool composition and removed timers.

packages/birmel/src/agent-tools/tools/automation/index.ts

shell.tsMinor update for new tool wrapper expectations +1/-1

Minor update for new tool wrapper expectations

• Aligns shell tool with the new tool factory/metadata requirements.

packages/birmel/src/agent-tools/tools/automation/shell.ts

index.tsAdjust birthday tool to new tool wrapper +1/-1

Adjust birthday tool to new tool wrapper

• Minor adaptation to the new tool creation/metadata behavior.

packages/birmel/src/agent-tools/tools/birthdays/index.ts

sqlite-query.tsAdjust sqlite query tool to new tool wrapper +1/-1

Adjust sqlite query tool to new tool wrapper

• Minor adaptation to the new tool creation/metadata behavior.

packages/birmel/src/agent-tools/tools/database/sqlite-query.ts

index.tsRecompose tool registry for AI SDK runtime +22/-33

Recompose tool registry for AI SDK runtime

• Updates the exported tool registry and removes/renames legacy tools (e.g., timers) for the new runtime.

packages/birmel/src/agent-tools/tools/index.ts

tool-sets.tsUpdate specialist tool sets and recording selection +27/-33

Update specialist tool sets and recording selection

• Aligns tool groupings with specialist routing and AI SDK tool execution/telemetry needs.

packages/birmel/src/agent-tools/tools/tool-sets.ts

index.tsMinor database wiring update +5/-1

Minor database wiring update

• Small adjustments to Prisma/database helpers to support new migration/bootstrap and runtime access patterns.

packages/birmel/src/database/index.ts

tracing.tsAdjust tracing helpers/attributes for new runtime +39/-57

Adjust tracing helpers/attributes for new runtime

• Updates tracing utilities to support the new runtime’s span naming and attribute conventions.

packages/birmel/src/observability/tracing.ts

hooks.tsRemove VoltAgent hooks module +0/-19

Remove VoltAgent hooks module

• Deletes legacy VoltAgent hooks; replaced by explicit runtime lifecycle and tooling.

packages/birmel/src/voltagent/agents/hooks.ts

routing-agent.tsRemove VoltAgent routing agent +0/-121

Remove VoltAgent routing agent

• Deletes the VoltAgent routing agent; replaced by agent-runtime/router.ts.

packages/birmel/src/voltagent/agents/routing-agent.ts

automation-agent.tsRemove VoltAgent automation agent +0/-49

Remove VoltAgent automation agent

• Deletes legacy specialist agent implementation now replaced by AI SDK ToolLoopAgent execution.

packages/birmel/src/voltagent/agents/specialized/automation-agent.ts

editor-agent.tsRemove VoltAgent editor agent +0/-48

Remove VoltAgent editor agent

• Deletes legacy specialist agent implementation now replaced by AI SDK ToolLoopAgent execution.

packages/birmel/src/voltagent/agents/specialized/editor-agent.ts

messaging-agent.tsRemove VoltAgent messaging agent +0/-47

Remove VoltAgent messaging agent

• Deletes legacy specialist agent implementation now replaced by AI SDK ToolLoopAgent execution.

packages/birmel/src/voltagent/agents/specialized/messaging-agent.ts

moderation-agent.tsRemove VoltAgent moderation agent +0/-50

Remove VoltAgent moderation agent

• Deletes legacy specialist agent implementation now replaced by AI SDK ToolLoopAgent execution.

packages/birmel/src/voltagent/agents/specialized/moderation-agent.ts

music-agent.tsRemove VoltAgent music agent +0/-49

Remove VoltAgent music agent

• Deletes legacy specialist agent implementation now replaced by AI SDK ToolLoopAgent execution.

packages/birmel/src/voltagent/agents/specialized/music-agent.ts

server-agent.tsRemove VoltAgent server agent +0/-55

Remove VoltAgent server agent

• Deletes legacy specialist agent implementation now replaced by AI SDK ToolLoopAgent execution.

packages/birmel/src/voltagent/agents/specialized/server-agent.ts

system-prompt.tsRemove VoltAgent system prompt module +0/-248

Remove VoltAgent system prompt module

• Deletes legacy prompt assembly; replaced by agent-runtime/prompts.ts and context bundling.

packages/birmel/src/voltagent/agents/system-prompt.ts

conversation-lock.tsRemove VoltAgent conversation lock +0/-60

Remove VoltAgent conversation lock

• Deletes legacy conversation lock; replaced by agent-runtime/turn-queue.ts.

packages/birmel/src/voltagent/conversation-lock.ts

sanitize.tsRemove VoltAgent memory sanitize module +0/-89

Remove VoltAgent memory sanitize module

• Deletes legacy sanitize logic; replaced by deterministic claim extraction + apply safeguards.

packages/birmel/src/voltagent/memory/sanitize.ts

message-handler.tsRemove VoltAgent streaming message handler +0/-260

Remove VoltAgent streaming message handler

• Deletes legacy message handler; replaced by agent-runtime/message-handler.ts with placeholder+edit delivery model.

packages/birmel/src/voltagent/message-handler.ts

message-stream.tsRemove VoltAgent message streaming module +0/-216

Remove VoltAgent message streaming module

• Deletes streaming infrastructure not used in the new one-reply-per-input runtime contract.

packages/birmel/src/voltagent/message-stream.ts

openai-provider-options.tsRemove VoltAgent provider options module +0/-51

Remove VoltAgent provider options module

• Deletes legacy OpenAI provider options; replaced by agent-runtime/provider-options.ts.

packages/birmel/src/voltagent/openai-provider-options.ts

should-respond-classifier.tsRemove VoltAgent should-respond classifier +0/-116

Remove VoltAgent should-respond classifier

• Deletes legacy classifier module; replaced by packages/birmel/src/discord/should-respond-classifier.ts.

packages/birmel/src/voltagent/should-respond-classifier.ts

create-tool.tsRemove VoltAgent tool wrapper +0/-84

Remove VoltAgent tool wrapper

• Deletes legacy tool wrapper; replaced by agent-runtime/tools/create-tool.ts with strict trust boundary enforcement.

packages/birmel/src/voltagent/tools/create-tool.ts

Tests (17) +3942 / -497
openclaw-capabilities-container.tsUpdate container capability E2E harness for Birmel 3 +106/-90

Update container capability E2E harness for Birmel 3

• Adjusts the capabilities container E2E test harness to align with the updated runtime behavior and dependencies.

packages/birmel/e2e/openclaw-capabilities-container.ts

openclaw-capabilities-docker.tsAlign docker E2E capability assertions +2/-4

Align docker E2E capability assertions

• Minor E2E corrections to match new image/runtime expectations.

packages/birmel/e2e/openclaw-capabilities-docker.ts

smoke.tsUpdate runtime smoke script expectations +3/-5

Update runtime smoke script expectations

• Adjusts runtime smoke checks for the new startup and health behavior.

packages/birmel/scripts/smoke.ts

automation.test.tsRestructure automation tests around isolated runtime suites +110/-372

Restructure automation tests around isolated runtime suites

• Rewrites/relocates automation tests to match the new explicit runtime and job execution behavior.

packages/birmel/src/agent-tools/tools/automation/automation.test.ts

test-setup.tsExpand automation test setup for job/session runtime +181/-26

Expand automation test setup for job/session runtime

• Adds fixtures/mocks for agent jobs, delivery, and request context to support the new runtime behavior.

packages/birmel/src/agent-tools/tools/automation/test-setup.ts

message-create-harness.tsAdd admission harness for new typed TurnInput flow +292/-0

Add admission harness for new typed TurnInput flow

• Introduces test harness utilities for exercising Discord admission decisions and message dispatch under the new runtime.

packages/birmel/tests/admission/message-create-harness.ts

message-create.test.tsAdd admission tests for triggers and authority boundary +27/-0

Add admission tests for triggers and authority boundary

• Tests mention/wake-word/engaged-follow-up/session-thread triggers and trusted-user gating.

packages/birmel/tests/admission/message-create.test.ts

environment.test.tsAdd config environment parsing tests +41/-0

Add config environment parsing tests

• Validates strict env parsing and required config behavior for the new runtime options.

packages/birmel/tests/config/environment.test.ts

context-bundle.test.tsAdd comprehensive context bundle assembly tests +581/-0

Add comprehensive context bundle assembly tests

• Covers budget enforcement, transcript/session ordering, and memory/lore fragment selection rules.

packages/birmel/tests/context/context-bundle.test.ts

no-database-write.test.tsAdd fixture ensuring no assembled prompt persistence +43/-0

Add fixture ensuring no assembled prompt persistence

• Asserts the runtime does not persist assembled prompts/transcripts beyond intended telemetry fields.

packages/birmel/tests/context/no-database-write.test.ts

migrations.test.tsAdd migration baseline and fixture tests +484/-0

Add migration baseline and fixture tests

• Validates baseline fingerprint verification, migration deployment, and rejection behavior on unexpected schemas.

packages/birmel/tests/database/migrations.test.ts

turn-flow.test.tsAdd end-to-end turn flow tests for new runtime +208/-0

Add end-to-end turn flow tests for new runtime

• Exercises admission → context → routing → execution → response edit → memory extraction flow in a controlled harness.

packages/birmel/tests/flow/turn-flow.test.ts

server.test.tsAdd health endpoint tests +162/-0

Add health endpoint tests

• Covers /live and /ready behavior and readiness gating on migrations/Discord/scheduler state.

packages/birmel/tests/health/server.test.ts

durable-jobs.test.tsAdd durable job execution tests with leasing/session logging +449/-0

Add durable job execution tests with leasing/session logging

• Validates atomic job execution behavior, trusted actor enforcement, and session event logging for scheduled work.

packages/birmel/tests/jobs/durable-jobs.test.ts

claim-memory.integration.test.tsAdd claim memory integration test suite +722/-0

Add claim memory integration test suite

• Validates candidate application, revision history, retrieval scoring, and safety checks (citations, embeddings).

packages/birmel/tests/memory/claim-memory.integration.test.ts

runtime.test.tsAdd runtime module tests (router/executors/tools) +167/-0

Add runtime module tests (router/executors/tools)

• Covers typed routing decisions, specialist execution boundaries, and tool metadata/creation contracts.

packages/birmel/tests/runtime/runtime.test.ts

session-runtime.test.tsAdd session runtime tests for thread binding and summaries +364/-0

Add session runtime tests for thread binding and summaries

• Validates sequenced event appends, context retrieval, and session state transitions for thread-bound sessions.

packages/birmel/tests/sessions/session-runtime.test.ts

Documentation (5) +485 / -100
AGENTS.mdUpdate root agent guidance references +2/-2

Update root agent guidance references

• Minor documentation tweaks aligning agent guidance with the new Birmel runtime structure.

AGENTS.md

AGENTS.mdRewrite Birmel agent guidance for explicit runtime architecture +96/-98

Rewrite Birmel agent guidance for explicit runtime architecture

• Updates internal contributor/operator guidance to reflect the new explicit runtime pipeline, memory, sessions, and job model.

packages/birmel/AGENTS.md

2026-08-08_birmel-3-single-explicit-agent-runtime.mdDocument explicit runtime architecture and migration plan +217/-0

Document explicit runtime architecture and migration plan

• Adds a detailed plan doc describing the Birmel 3 explicit runtime, memory, sessions, job model, and rollout steps.

packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md

birmel.mdAdd Birmel wiki page for operators/users +143/-0

Add Birmel wiki page for operators/users

• Adds documentation describing Birmel’s behavior, configuration, and runtime expectations.

packages/docs/wiki/src/content/docs/birmel.md

README.mdDocument glitter-context package +27/-0

Document glitter-context package

• Adds usage documentation and intent for the new friend-context lore engine.

packages/glitter-context/README.md

Other (48) +6046 / -576
smoke-app-in-image.tsAdjust in-image smoke test for new startup/migration flow +2/-3

Adjust in-image smoke test for new startup/migration flow

• Updates the Buildkite image smoke script to match the new runtime start behavior and dependency expectations.

.buildkite/scripts/smoke-app-in-image.ts

.quality-baseline.jsonUpdate quality baseline after runtime rewrite +1/-2

Update quality baseline after runtime rewrite

• Refreshes the repository quality baseline to reflect the new code and removed legacy modules.

.quality-baseline.json

.env.exampleExpand/rename env vars for authority, health, and memory models +91/-39

Expand/rename env vars for authority, health, and memory models

• Adds new environment variables (trusted users, health port, memory/embedding models, agent timeouts) and removes legacy/VoltAgent-related variables.

packages/birmel/.env.example

package.jsonUpdate dependencies/scripts for explicit AI SDK runtime +5/-7

Update dependencies/scripts for explicit AI SDK runtime

• Adjusts package dependencies and scripts to support the new runtime modules, migration bootstrap, and test layout.

packages/birmel/package.json

migration.sqlRemove obsolete migration superseded by baseline +0/-116

Remove obsolete migration superseded by baseline

• Deletes a legacy migration file now replaced by the verified baseline migration strategy.

packages/birmel/prisma/migrations/20251222203142_add_polls_activity_birthdays/migration.sql

migration.sqlRemove obsolete migration superseded by baseline +0/-25

Remove obsolete migration superseded by baseline

• Deletes a legacy migration file now replaced by the verified baseline migration strategy.

packages/birmel/prisma/migrations/20251223072521_add_scheduled_task/migration.sql

migration.sqlRemove obsolete migration superseded by baseline +0/-111

Remove obsolete migration superseded by baseline

• Deletes a legacy migration file now replaced by the verified baseline migration strategy.

packages/birmel/prisma/migrations/20260603000000_add_agent_runtime_capabilities/migration.sql

migration.sqlAdd baseline migration snapshot for existing schema +376/-0

Add baseline migration snapshot for existing schema

• Introduces a baseline migration used for fingerprint verification and safe 'migrate resolve' on existing databases.

packages/birmel/prisma/migrations/20260808000000_baseline/migration.sql

migration.sqlAdd additive migration for Birmel 3 runtime tables/columns +271/-0

Add additive migration for Birmel 3 runtime tables/columns

• Creates new runtime tables (AgentRun, MemoryClaim/Revision, archives) and extends sessions/jobs for leases and thread binding.

packages/birmel/prisma/migrations/20260808010000_birmel_3_runtime/migration.sql

schema.prismaOverhaul schema for claim memory, agent runs, sessions, and job leasing +158/-97

Overhaul schema for claim memory, agent runs, sessions, and job leasing

• Adds MemoryClaim/MemoryRevision and AgentRun, updates AgentJob and AgentSession models (thread uniqueness, actor fields, leasing), and removes legacy AgentMemory/ScheduledTask concepts from the runtime path.

packages/birmel/prisma/schema.prisma

migrate.tsAdd migration deploy script using baseline verification +3/-0

Add migration deploy script using baseline verification

• Provides an entrypoint to run deployDatabaseMigrations as part of deployment/startup workflows.

packages/birmel/scripts/migrate.ts

start.tsAdd start script that runs migration bootstrap before app +5/-0

Add start script that runs migration bootstrap before app

• Ensures migrations are deployed/resolved before starting the Birmel runtime process.

packages/birmel/scripts/start.ts

agent-runs.tsPersist AgentRun admission/dedup and lifecycle fields +97/-0

Persist AgentRun admission/dedup and lifecycle fields

• Implements unique-constraint-based Discord turn deduplication and stores run context/route/completion/failure metadata for telemetry.

packages/birmel/src/agent-runtime/agent-runs.ts

contracts.tsDefine typed contracts for turns, routing, context, tools, and memory +226/-0

Define typed contracts for turns, routing, context, tools, and memory

• Centralizes zod schemas for TurnInput, ContextBundle, RouteDecision, tool metadata, and memory candidates/claims.

packages/birmel/src/agent-runtime/contracts.ts

job-agent.tsExecute isolated automation agent for AgentJob runs +93/-0

Execute isolated automation agent for AgentJob runs

• Runs a specialist automation agent with compact persona projection and optional session context, applying job execution options.

packages/birmel/src/agent-runtime/job-agent.ts

memory-extraction.tsExtract durable memory candidates and apply as claims with citations +126/-0

Extract durable memory candidates and apply as claims with citations

• Performs post-response extraction from raw transcript, enforces source message citations, embeds candidates, and writes claim revisions via applyMemoryCandidates.

packages/birmel/src/agent-runtime/memory-extraction.ts

message-handler.tsImplement explicit end-to-end turn processing pipeline +304/-0

Implement explicit end-to-end turn processing pipeline

• Orchestrates placeholder reply, context assembly, routing, agent execution, single edited response delivery, session event logging, and post-turn memory extraction with incident handling.

packages/birmel/src/agent-runtime/message-handler.ts

prompts.tsAdd core policy and router/specialist instructions +38/-0

Add core policy and router/specialist instructions

• Defines shared prompt text used by the router and agent executors.

packages/birmel/src/agent-runtime/prompts.ts

router.tsRoute turns with structured AI SDK output +69/-0

Route turns with structured AI SDK output

• Uses classifier model + strict schema output to decide direct vs specialist routing with tracing attributes.

packages/birmel/src/agent-runtime/router.ts

runtime.tsDispatch routed turns to direct or specialist execution +68/-0

Dispatch routed turns to direct or specialist execution

• Builds a validated SpecialistTaskPacket and invokes the configured executor for the chosen route.

packages/birmel/src/agent-runtime/runtime.ts

specialists.tsReplace VoltAgent agents with AI SDK executors +199/-0

Replace VoltAgent agents with AI SDK executors

• Implements direct generation and specialist ToolLoopAgent execution with tool sets, step limits, and usage telemetry.

packages/birmel/src/agent-runtime/specialists.ts

create-tool.tsEnforce trusted context and timeouts for tool execution +176/-0

Enforce trusted context and timeouts for tool execution

• Wraps tools with request-context validation, trusted-user boundary, single-reply enforcement, timeouts, and tracing/logging.

packages/birmel/src/agent-runtime/tools/create-tool.ts

tool-metadata.tsRegister stable tool metadata for routing/safety +106/-0

Register stable tool metadata for routing/safety

• Defines per-tool specialist ownership, risk class, timeouts, and required request context fields.

packages/birmel/src/agent-runtime/tools/tool-metadata.ts

turn-queue.tsEnsure ordered turn processing per session/channel +26/-0

Ensure ordered turn processing per session/channel

• Adds a small queue/lock to serialize turns by sessionId or channelId, replacing legacy conversation locks.

packages/birmel/src/agent-runtime/turn-queue.ts

index.tsAdd strict env parsing and new config sections (authority/agent/health/editor) +166/-135

Add strict env parsing and new config sections (authority/agent/health/editor)

• Moves parsing to zod-backed helpers, adds trusted-user authority config, agent timeouts/step limits, memory/embedding model settings, and editor/github config structure.

packages/birmel/src/config/index.ts

schema.tsExtend config schema for new runtime surface area +82/-33

Extend config schema for new runtime surface area

• Updates zod schema definitions to validate new configuration keys required by the explicit runtime.

packages/birmel/src/config/schema.ts

context-bundle.tsAssemble bounded context bundle with budgets and ranking +308/-0

Assemble bounded context bundle with budgets and ranking

• Adds a deterministic context assembly routine that selects transcript/session events and ranked memory/lore fragments within character budgets.

packages/birmel/src/context/context-bundle.ts

turn-context.tsConstruct per-turn context from transcript, memory claims, sessions, and Glitter lore +213/-0

Construct per-turn context from transcript, memory claims, sessions, and Glitter lore

• Builds embeddings for query scoring, retrieves scoped memory claims, injects Glitter friend context, and produces the final ContextBundle with tracing.

packages/birmel/src/context/turn-context.ts

migration-bootstrap.tsReplace db push with baseline fingerprint verification + migrate deploy +197/-0

Replace db push with baseline fingerprint verification + migrate deploy

• Implements SQLite fingerprint checks to verify an existing database matches the baseline, resolves baseline if needed, then deploys migrations safely.

packages/birmel/src/database/migration-bootstrap.ts

should-respond-classifier.tsAdd should-respond classifier outside VoltAgent +72/-0

Add should-respond classifier outside VoltAgent

• Introduces an explicit classifier module used for engaged-follow-up admission decisions.

packages/birmel/src/discord/should-respond-classifier.ts

server.tsAdd /live and /ready endpoints for probes +82/-0

Add /live and /ready endpoints for probes

• Exposes liveness/readiness endpoints checking database connectivity, required migrations, Discord readiness, and scheduler started state.

packages/birmel/src/health/server.ts

apply.tsImplement deterministic claim memory apply with revision history +500/-0

Implement deterministic claim memory apply with revision history

• Adds claim reconciliation logic that produces MemoryRevision entries and updates/supersedes claims deterministically.

packages/birmel/src/memory/apply.ts

identity.tsAdd stable identity key derivation for memory claims +145/-0

Add stable identity key derivation for memory claims

• Computes identity keys used to deduplicate and update claims across revisions.

packages/birmel/src/memory/identity.ts

operations.tsAdd memory claim persistence operations +153/-0

Add memory claim persistence operations

• Introduces persistence helpers used by apply/retrieve flows for MemoryClaim and MemoryRevision rows.

packages/birmel/src/memory/operations.ts

retrieve.tsRetrieve and score memory claims for context injection +285/-0

Retrieve and score memory claims for context injection

• Implements scope/temporal applicability and lexical/semantic similarity scoring, selecting top claims within limits.

packages/birmel/src/memory/retrieve.ts

schemas.tsDefine memory retrieval contracts +172/-0

Define memory retrieval contracts

• Adds zod contracts for memory retrieval inputs/results and retrieved claim representations.

packages/birmel/src/memory/schemas.ts

serialization.tsAdd embedding and Discord-id serialization utilities +47/-0

Add embedding and Discord-id serialization utilities

• Normalizes and serializes embeddings and related Discord IDs for storage and retrieval.

packages/birmel/src/memory/serialization.ts

stored.tsAdd stored claim parsing and revision joining +127/-0

Add stored claim parsing and revision joining

• Converts Prisma rows into typed structures with revisions to support deterministic apply/retrieve operations.

packages/birmel/src/memory/stored.ts

telemetry.tsAdd memory telemetry spans +27/-0

Add memory telemetry spans

• Adds helpers to standardize tracing around memory operations without logging prompt content.

packages/birmel/src/memory/telemetry.ts

projection.tsCreate compact persona projection for bounded context +55/-0

Create compact persona projection for bounded context

• Adds a compact, reusable persona projection used by routing, execution, memory extraction, and job agents.

packages/birmel/src/persona/projection.ts

agent-job-schedule.tsIntroduce AgentJob scheduling helper for atomic execution +70/-0

Introduce AgentJob scheduling helper for atomic execution

• Adds leasing/claiming oriented scheduling logic to prevent duplicate job execution and support durable work.

packages/birmel/src/scheduler/agent-job-schedule.ts

service.tsAdd thread-bound AgentSession service with ordered events +151/-0

Add thread-bound AgentSession service with ordered events

• Implements session creation with Discord thread binding, robust sequenced event appends, context retrieval, and status transitions.

packages/birmel/src/sessions/service.ts

summarization.tsAdd session summarization logic to bound context growth +86/-0

Add session summarization logic to bound context growth

• Summarizes sessions when needed and tracks summary progression via sequence/version fields.

packages/birmel/src/sessions/summarization.ts

friend-context.tsImplement friend-context lore selection engine +452/-0

Implement friend-context lore selection engine

• Provides character-budgeted lore/context selection for use during Birmel context construction.

packages/glitter-context/src/friend-context.ts

friend-context-lore.tsAdd lore corpus for friend-context +83/-0

Add lore corpus for friend-context

• Defines the lore sections used by friend-context selection.

packages/glitter-context/src/friend-context-lore.ts

schema.tsDefine friend-context zod schemas +79/-0

Define friend-context zod schemas

• Adds input/output schemas and types for friend-context calls.

packages/glitter-context/src/schema.ts

index.tsExport glitter-context public API +30/-0

Export glitter-context public API

• Exposes getFriendContext and supporting types for consumption by Birmel.

packages/glitter-context/src/index.ts

index.tsUpdate k8s resources for new health endpoints/runtime needs +24/-8

Update k8s resources for new health endpoints/runtime needs

• Adjusts manifests to support readiness/liveness probes and related runtime configuration changes.

packages/homelab/src/cdk8s/src/resources/birmel/index.ts

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (2) 📜 Skill insights (0)

Grey Divider


Action required

1. Timeout releases job lease 🐞 Bug ☼ Reliability
Description
When an agent job times out, the timeout wrapper does not cancel the underlying execution, but
failure handling clears the job lease (claimedBy/leaseExpiresAt), allowing the same job to be
re-claimed and executed again while the first execution may still be performing side effects (tool
execution / Discord delivery). This can produce duplicate messages or repeated tool actions for a
single scheduled run.
Code

packages/birmel/src/scheduler/jobs/agent-jobs.ts[R125-127]

+        claimedAt: null,
+        claimedBy: null,
+        leaseExpiresAt: null,
Evidence
withAgentJobTimeout uses Promise.race (no cancellation), while markJobFailure clears the lease
fields that gate claiming. Because durable execution can send Discord messages or execute tools, a
reclaim can duplicate side effects.

packages/birmel/src/scheduler/agent-job-schedule.ts[174-190]
packages/birmel/src/scheduler/jobs/agent-jobs.ts[91-129]
packages/birmel/src/scheduler/jobs/agent-jobs.ts[165-209]
packages/birmel/src/scheduler/jobs/scheduled-tasks.ts[272-287]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Agent jobs are timed out via `Promise.race`, which does **not** stop the underlying `executeDurableAgentJob` work. On timeout, the code immediately clears `claimedBy`/`leaseExpiresAt`, making the job eligible for re-claim/retry while the original execution may still be running and causing side effects (Discord sends, tool writes).
## Issue Context
- Timeouts are currently used as a control-flow mechanism, not a cancellation mechanism.
- Durable jobs can perform external side effects (Discord delivery) and invoke tools.
## Fix Focus Areas
- packages/birmel/src/scheduler/agent-job-schedule.ts[174-191]
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[91-131]
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[165-210]
- packages/birmel/src/scheduler/jobs/scheduled-tasks.ts[272-287]
## Implementation direction
Choose one of these safe approaches:
1) **Abortable execution**: Change `withAgentJobTimeout` to use an `AbortController` and pass an `AbortSignal` down into `executeDurableAgentJob` and any tool/agent/Discord operations so they can stop promptly. Only clear the lease after the operation settles (or is confirmed aborted).
2) **Lease fencing on timeout** (no cancellation): If the failure is a timeout, do **not** clear `claimedBy`/`leaseExpiresAt` in `markJobFailure`. Keep the job in `running` until the lease naturally expires, and let `recoverExpiredJobLeases()` transition it to `retrying`/`recovered`.
3) **Idempotency key fencing**: Introduce an execution/run id that tools and delivery paths must include and enforce idempotency (e.g., “at-most-once delivery” keyed by job run id), and keep the lease until completion.
Add/adjust tests to cover: timeout -> underlying work continues -> job should not be immediately reclaimable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Job timeout not cancellable 🐞 Bug ☼ Reliability ⭐ New
Description
withAgentJobTimeout() rejects on timeout via Promise.race(), but does not abort the underlying
executeDurableAgentJob() promise, so job work may continue after the scheduler records a failure and
schedules a retry. This can lead to overlapping executions and duplicate external side effects when
the underlying operation is slow or stuck.
Code

packages/birmel/src/scheduler/agent-job-schedule.ts[R184-187]

+  try {
+    return await Promise.race([operation, timeout]);
+  } finally {
+    if (timeoutId !== undefined) {
Evidence
The timeout helper returns Promise.race([operation, timeout]), which can reject while operation
continues executing; the scheduler then treats this as a failure and moves the job state forward
even though durable execution includes message/tool side effects.

packages/birmel/src/scheduler/agent-job-schedule.ts[174-190]
packages/birmel/src/scheduler/jobs/agent-jobs.ts[181-210]
packages/birmel/src/scheduler/jobs/scheduled-tasks.ts[223-288]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`withAgentJobTimeout()` implements timeouts with `Promise.race()`, which does not cancel the underlying job execution. If the timeout fires, the scheduler can mark the run failed and schedule a retry while the original job continues running and may still deliver messages / run tools.

### Issue Context
- The scheduler wraps `executeDurableAgentJob()` with `withAgentJobTimeout()` and then transitions job state on error.
- Durable jobs can send Discord messages and execute tools.

### Fix Focus Areas
- packages/birmel/src/scheduler/agent-job-schedule.ts[174-191]
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[194-210]
- packages/birmel/src/scheduler/jobs/scheduled-tasks.ts[223-287]

### Implementation direction
- Change `withAgentJobTimeout` to be *cooperatively cancellable*, e.g. accept a callback `(signal: AbortSignal) => Promise<T>` and create an `AbortController` that is aborted on timeout.
- Thread the `AbortSignal` through the durable job execution path (tool execution + Discord delivery).
- At minimum, ensure side-effect boundaries (Discord sends, destructive tool calls) check `signal.aborted` before performing the action and fail fast if aborted.
- Consider keeping the lease until the underlying work is known stopped, or ensuring retries cannot overlap with still-running work.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Tool timeout not cancellable 🐞 Bug ☼ Reliability ⭐ New
Description
createTool() enforces timeouts with Promise.race() but does not provide an AbortSignal or other
cancellation mechanism to the tool implementation, so timed-out tools may keep running and still
perform side effects after the runtime considers the call failed. This is especially risky for
Discord write tools like manage-message, where a delayed API call can still send/edit/delete after
the timeout.
Code

packages/birmel/src/agent-runtime/tools/create-tool.ts[R104-107]

+  try {
+    return await Promise.race([operation, timeoutPromise]);
+  } finally {
+    if (timeout !== undefined) {
Evidence
The wrapper withTimeout returns Promise.race([operation, timeoutPromise]) and clears only the
timer; the underlying operation continues unless it self-cancels. Tools like manage-message
perform Discord write operations and do not receive any cancellation token from the wrapper.

packages/birmel/src/agent-runtime/tools/create-tool.ts[92-110]
packages/birmel/src/agent-tools/tools/discord/messages.ts[28-120]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The tool wrapper timeout uses `Promise.race()` without cancelling the underlying tool execution. If the wrapper times out, the agent/runtime proceeds as though the tool failed, but the tool may still complete later and perform external side effects.

### Issue Context
- Many tools perform Discord API writes; they are not currently passed any cancellation token.
- A timeout should ideally stop or prevent side effects, or at least make side effects idempotent/guarded.

### Fix Focus Areas
- packages/birmel/src/agent-runtime/tools/create-tool.ts[92-110]
- packages/birmel/src/agent-tools/tools/discord/messages.ts[28-120]

### Implementation direction
- Extend the tool execute contract to accept an `AbortSignal` (or a small context object containing it).
- Implement the timeout using an `AbortController`, aborting the signal on timeout.
- For side-effecting tools (Discord writes, shell, browser), check `signal.aborted` before issuing the side effect, and where possible pass `signal` into underlying APIs (or add explicit cleanup/kill logic).
- Optionally, on timeout, prevent any late result from being acted upon (e.g., by verifying an execution token before applying effects).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Checked tasks under ## Remaining 📘 Rule violation ⚙ Maintainability
Description
The plan uses pre-checked task items (- [x]) under ## Remaining, but the rule requires agent
work items to be represented as unchecked Markdown tasks (- [ ]). This breaks the standardized
format for tracking remaining work.
Code

packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md[R180-183]

+- [x] Mirror the approved contracts in code and add the baseline/additive
+      schema migrations.
+- [x] Replace VoltAgent orchestration, memory, and tool adaptation with the
+      explicit AI SDK runtime.
Evidence
PR Compliance ID 2598586 requires that agent work items under a ## Remaining heading be
represented as unchecked tasks (- [ ]) and explicitly disallows pre-checked items. The plan
currently includes multiple - [x] entries under ## Remaining.

Rule 2598586: Represent agent work items as unchecked Markdown tasks under a ## Remaining heading
packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md[178-193]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`## Remaining` contains pre-checked tasks (`- [x]`), but remaining agent work items must be unchecked (`- [ ]`).
## Issue Context
This plan is tracked as a board item and should follow the standardized remaining-work format.
## Fix Focus Areas
- packages/docs/plans/2026-08-08_birmel-3-single-explicit-agent-runtime.md[178-196]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
5. Edited ## Comment Log entry 📘 Rule violation ⚙ Maintainability
Description
A previously existing ## Comment Log entry was modified instead of only appending new entries.
This violates the append-only requirement for comment logs and can compromise auditability of change
history.
Code

packages/docs/todos/birmel-tests-polish.md[R52-55]

+### 2026-08-08 — Birmel 3.0 implementation

-- Retained as active. The repository still has broad unit coverage and several
-  component e2e scripts, but no committed deterministic message-to-tool
-  delegation test or recorded full Discord happy-path proof.
+- Replaced the stale VoltAgent-era testing inventory with the current explicit
+  runtime contract. Automated coverage is complete; only direct production
Evidence
PR Compliance ID 2598594 requires ## Comment Log sections to be append-only; existing lines must
not be changed or removed. The change replaces the prior dated entry rather than appending a new one
to the end of the section.

Rule 2598594: Comment log sections must be append-only
packages/docs/todos/birmel-tests-polish.md[50-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`## Comment Log` sections must be append-only, but the PR edits/replaces an existing log entry instead of adding a new entry at the end.
## Issue Context
Comment logs are treated as an audit trail; modifying prior entries breaks that guarantee.
## Fix Focus Areas
- packages/docs/todos/birmel-tests-polish.md[50-56]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Burst agent-job concurrency 🐞 Bug ➹ Performance
Description
The scheduler now executes all due agent jobs in parallel (up to 25 at once) via Promise.allSettled
without a concurrency limiter, which can spike resource usage and outbound calls. This increases the
likelihood of rate limits and operational instability when jobs involve model calls, browser
automation, or Discord actions.
Code

packages/birmel/src/scheduler/jobs/agent-jobs.ts[R302-304]

+  const results = await Promise.allSettled(
+    dueJobs.map((job) => trackJobExecution(processAgentJob(job))),
+  );
Evidence
The code explicitly selects up to 25 due jobs and executes them via Promise.allSettled over the
mapped job processors, which starts them concurrently with no additional throttling.

packages/birmel/src/scheduler/jobs/agent-jobs.ts[286-304]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`runAgentJobsTick` launches all due jobs concurrently (bounded only by `take: 25`) using `Promise.allSettled(dueJobs.map(processAgentJob))`. This creates bursty load and can overwhelm shared resources or external dependencies.
## Issue Context
Each `processAgentJob` can execute tools and/or Discord delivery, and may involve expensive work. Even with a batch limit of 25, running all 25 simultaneously can be too aggressive depending on deployment size and provider limits.
## Fix Focus Areas
- packages/birmel/src/scheduler/jobs/agent-jobs.ts[286-311]
## Implementation direction
- Introduce a concurrency limiter (e.g., a simple semaphore or `p-limit`) and run jobs with `maxConcurrentAgentJobs` from config.
- Keep `take: 25` as a fetch batch size, but process in chunks respecting the concurrency limit.
- Optionally add jitter/backoff when many jobs are due simultaneously.
Add tests or assertions ensuring no more than N jobs are started concurrently per tick.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread packages/birmel/src/scheduler/agent-job-schedule.ts
Comment thread packages/birmel/src/agent-runtime/tools/create-tool.ts Outdated
@shepherdjerred

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9ef54d185

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

SELECT
"id", "guildId", "channelId", "threadId", "userId", "channelId",
"name", "description", "scheduleKind", "scheduleValue", "timezone",
"nextRunAt", "status", "payloadKind", "message", "toolId", "toolInput",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Migrate removed tool IDs in existing jobs

When production contains a pending AgentJob whose toolId is manage-task or manage-scheduled-message, this copy preserves that ID even though the new allTools registry no longer includes either tool, so executeRegisteredTool will fail every run with “Tool not found or not executable.” The fresh migration handles legacy ScheduledTask/send-message rows, but it also needs to translate existing AgentJob payloads or retain compatibility executors for their stable IDs.

AGENTS.md reference: packages/birmel/AGENTS.md:L34-L34

Useful? React with 👍 / 👎.

Comment on lines +434 to +436
claimedAt: null,
claimedBy: null,
leaseExpiresAt: null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Finalize the run when cancelling an active job

When cancel targets a currently running job, clearing claimedBy makes both markJobSuccess and markJobFailure fail their status = 'running' AND claimedBy = claimId fence; those functions then return before updating the associated AgentJobRun. The job remains cancelled, but its run history is permanently stuck at running because lease recovery only scans jobs whose status is still running. Either reject cancellation while running or explicitly finalize/fence the active run without discarding its claim bookkeeping.

AGENTS.md reference: packages/birmel/AGENTS.md:L68-L71

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6f56b03fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +239 to +240
await failedResponseMessage.edit(
`I couldn't complete that request. Reference: ${reference}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep completed delivery out of the failure path

When a specialist has already performed its action and the final Discord edit succeeds, a later failure in appendCompletedSessionEvents or completeAgentRun enters this catch and overwrites the successful response with an incident message. The user is then told the request failed even though its write or destructive action may have completed, encouraging a duplicate retry and producing a second final edit; post-delivery persistence failures need handling that preserves the delivered result.

AGENTS.md reference: packages/birmel/AGENTS.md:L23-L25

Useful? React with 👍 / 👎.

{ once: true },
);
});
return await Promise.race([operation(controller.signal), abortPromise]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wait for timed-out tool work to stop

When a tool ignores the supplied signal—as most existing tools do, including manage-role, whose executor only accepts ctx—this race rejects at the timeout while operation continues running. The agent or durable-job runner can therefore record failure and retry while the original write later completes, duplicating messages, roles, or other side effects; timeout handling must not relinquish the operation until it has actually stopped, or every registered tool must enforce abort-aware cancellation.

Useful? React with 👍 / 👎.

Comment on lines +29 to +31
kind: z.literal("tool"),
toolId: z.string().min(1),
input: z.record(z.string(), z.unknown()).default({}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate stored tool payloads before accepting jobs

For a tool job, this schema accepts any nonempty ID and arbitrary input, so createAgentJob reports success and persists typos, removed IDs, or arguments that violate the registered tool's Zod schema. Validation occurs only when the delayed execution calls tool.execute, potentially hours later, at which point every attempt fails; creation and editing should resolve the stable registry entry and validate its input before storing the job.

AGENTS.md reference: packages/birmel/AGENTS.md:L34-L35

Useful? React with 👍 / 👎.

@shepherdjerred

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6f56b03fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +66 to +68
const objectInput = ObjectInputSchema.safeParse(input);
if (!objectInput.success || !("guildId" in objectInput.data)) {
return input;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Inject the runtime guild when the model omits it

When an input schema makes guildId optional, this returns the model input unchanged if the field is omitted rather than deriving the guild from RequestContext. For example, manage-election accepts an omitted guild but then passes undefined to most handlers, so otherwise valid calls fail even though trusted guild context is available; always inject the runtime guild into object inputs rather than requiring the key to be model-supplied.

AGENTS.md reference: packages/birmel/AGENTS.md:L39-L39

Useful? React with 👍 / 👎.

Comment on lines +179 to +182
step.toolResults.map((toolResult) => ({
toolId: toolResult.toolName,
content: `Tool ${toolResult.toolName} completed`,
})),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve failed tool outcomes in session events

When a tool returns a validated failure such as { success: false, message: ... }, AI SDK still includes it in step.toolResults, but this hard-codes the event as “completed” and discards the result. Active sessions therefore persist failed writes as successful tool summaries, and later context or summarization can treat an action that never happened as verified; derive a bounded summary/status from the validated tool result instead.

AGENTS.md reference: packages/birmel/AGENTS.md:L63-L65

Useful? React with 👍 / 👎.

Comment on lines +299 to +300
await withTurnQueue(queueId, async () => {
await processAdmittedTurn(context, run.id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recheck session status after waiting in the turn queue

When two thread messages are admitted close together and the first turn archives or cancels the session, the second already holds the old activeSessionId and runs after the first without rechecking session state. This lets a causally later queued turn execute and append events after cancellation, so verify that the session is still active once the queue is acquired before processing it.

AGENTS.md reference: packages/birmel/AGENTS.md:L66-L67

Useful? React with 👍 / 👎.

Comment on lines +361 to +365
prisma.agentJobRun.updateMany({
where: {
jobId: { in: staleIds },
status: { in: ["running", "timed_out"] },
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fence recovered runs to the expired claim

When two recovery callers observe the same expired job, one can recover and re-claim it before the other's transaction starts; this unqualified run update then marks the newly created active run as recovered, even though the following job update rejects its fresh lease. The new execution continues, but success/failure finalization cannot update that run because it is no longer running, corrupting run history; recover only the run associated with the expired claim and only when the matching job transition succeeds.

AGENTS.md reference: packages/birmel/AGENTS.md:L68-L71

Useful? React with 👍 / 👎.

@shepherdjerred

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ac41b95d0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const config = getConfig();
return {
openai: {
store: false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include encrypted reasoning for stateless tool loops

When the configured reasoning model invokes a tool, ToolLoopAgent makes a follow-up Responses request, but store: false requires the preceding reasoning item to be returned as encrypted content for that next step. The replaced src/voltagent/openai-provider-options.ts explicitly requested include: ["reasoning.encrypted_content"] for this reason; dropping it here can make every specialist tool call fail after its first step instead of producing a final response. Restore that include option while retaining stateless storage.

AGENTS.md reference: packages/birmel/AGENTS.md:L19-L22

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant