Skip to content

feat: tool spend as a first-class primitive with reserve/settle parit…#38

Merged
shivamfloe merged 8 commits into
mainfrom
feat/tool-tracking
Jul 21, 2026
Merged

feat: tool spend as a first-class primitive with reserve/settle parit…#38
shivamfloe merged 8 commits into
mainfrom
feat/tool-tracking

Conversation

@shivamfloe

@shivamfloe shivamfloe commented Jul 17, 2026

Copy link
Copy Markdown
Member

…y (py 0.5.0 / js 0.4.0).

Summary

  • New Features

    • Added shared budget enforcement for LLM token usage and paid tool calls.
    • Added tool-call reservation and settlement support to prevent calls that would exceed the ceiling.
    • Added per-tool spend tracking through tool_costs/toolCosts.
    • Added an example demonstrating tool-budget enforcement and spend attribution.
  • Documentation

    • Updated Python and JavaScript documentation with tool-spend workflows and behavior details.
  • Release

    • Python version updated to 0.5.0; JavaScript version updated to 0.4.0.

Testing

How was this tested?

  • pytest passes (Python changes)
  • ruff check . and ruff format . are clean (Python changes)
  • npm test and npm run typecheck pass in js/ (TypeScript changes)
  • Cost-map copies still match (src/floe_guard/cost_map.json == js/src/cost_map.json)
  • CHANGELOG.md updated (user-facing changes)

Summary by CodeRabbit

  • New Features

    • Added shared budget enforcement for LLM token usage and paid tool calls.
    • Added pre-call tool cost reservations and post-call settlement.
    • Added per-tool spend tracking and reporting.
    • Added examples demonstrating tool-spend safeguards without real API usage.
  • Documentation

    • Updated Python and JavaScript documentation with tool budget guidance and usage examples.
  • Tests

    • Added coverage for validation, reservations, shared ceilings, per-tool totals, and concurrent usage.
  • Chores

    • Updated the JavaScript package version to 0.5.0.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@shivamfloe, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6a354a55-22e4-48af-93ca-7113eaf9d5e1

📥 Commits

Reviewing files that changed from the base of the PR and between 789f427 and 193cd56.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • README.md
  • js/src/guard.ts
  • js/test/tool-costs.test.ts
  • pyproject.toml
  • src/floe_guard/__init__.py
  • src/floe_guard/guard.py
  • tests/test_anthropic_adapter.py
  • tests/test_openai_adapter.py
  • tests/test_tool_costs.py
📝 Walkthrough

Walkthrough

Floe Guard now enforces a shared ceiling across LLM tokens and paid tools in Python and JavaScript, adding reservation/settlement APIs, per-tool accounting, unified ledger events, validation, concurrency tests, documentation, and an example.

Changes

Tool budget enforcement

Layer / File(s) Summary
Python tool budget contract
src/floe_guard/..., tests/test_tool_costs.py
Python adds tool reservation, settlement, per-tool accounting, unified ledger events, and validation, looping, release, and concurrency tests.
JavaScript tool budget contract
js/src/guard.ts, js/test/tool-costs.test.ts, js/package.json
JavaScript adds equivalent tool APIs, snapshot accounting, delegated recording, extensive Vitest coverage, and version 0.5.0.
Tool budget documentation and example
README.md, js/README.md, examples/tool_budget.py
Documentation and the example describe shared token/tool ceilings, reservation flows, post-hoc metering, and spend attribution.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Agent
  participant BudgetGuard
  participant PaidTool
  participant SpendLedger
  Agent->>BudgetGuard: reserve tool estimate
  BudgetGuard-->>Agent: reservation or BudgetExceeded
  Agent->>PaidTool: execute paid call
  PaidTool-->>Agent: actual cost
  Agent->>BudgetGuard: settle tool cost
  BudgetGuard->>SpendLedger: record tool event and update totals
Loading

Possibly related PRs

Suggested reviewers: achris7, rajbhensdadiya

Poem

I reserve a carrot, then settle the bite,
Tools and tokens share one ceiling tonight.
The ledger grows tidy, each tool gets its due,
No runaway calls hop the budget fence through.
Binky hooray for the guard’s shiny rule!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.10% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding tool spend as a first-class primitive with reserve/settle support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tool-tracking

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/floe_guard/guard.py`:
- Around line 375-391: Validate tool estimates in reserve_tool and
js/src/guard.ts before delegating to reserve: reject None/undefined, non-finite,
and negative values, while preserving valid exact-cost reservations. Apply the
corresponding validation at both listed sites: src/floe_guard/guard.py lines
375-391 and js/src/guard.ts lines 333-350.
- Around line 393-423: The numeric reserved handle in settle_tool can release
unrelated in-flight reservations and be reused; replace numeric reservation
tracking with opaque, single-use reservation IDs registered when reservations
are created, and atomically validate and consume the matching ID during
settle_tool or release in src/floe_guard/guard.py lines 393-423. Implement the
same single-use reservation-token contract in js/src/guard.ts lines 365-380 for
parity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3e2227bf-b63a-4b3c-b4af-1c25987b8bc6

📥 Commits

Reviewing files that changed from the base of the PR and between af8019a and 442c07b.

⛔ Files ignored due to path filters (1)
  • js/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (11)
  • CHANGELOG.md
  • README.md
  • examples/tool_budget.py
  • js/README.md
  • js/package.json
  • js/src/guard.ts
  • js/test/tool-costs.test.ts
  • pyproject.toml
  • src/floe_guard/__init__.py
  • src/floe_guard/guard.py
  • tests/test_tool_costs.py

Comment thread src/floe_guard/guard.py
Comment thread src/floe_guard/guard.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds “tool spend” as a first-class part of Floe Guard’s shared USD ceiling, so paid API/tool calls can be reserved/settled like LLM calls and attributed per tool name.

Changes:

  • Introduces tool reservation + settlement APIs (reserve_tool/settle_tool and reserveTool/settleTool) and per-tool totals (tool_costs / toolCosts) under the same ceiling as token spend.
  • Updates accounting/logging so tool spend lands in the spend ledger and can participate in “stop-before” enforcement behavior.
  • Adds cross-language tests plus docs/examples and bumps package versions + changelog.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/test_tool_costs.py New Python tests covering reserve/settle tool flows, attribution, and mixed concurrency.
src/floe_guard/guard.py Implements tool reservations/settlements, tool attribution totals, and related docs.
src/floe_guard/init.py Updates package messaging and bumps Python __version__.
README.md Documents tool spend under the shared ceiling and the new APIs.
pyproject.toml Bumps Python package version.
js/test/tool-costs.test.ts New TS tests for tool spend APIs, attribution, and mixed interleaving.
js/src/guard.ts Implements TS tool reservation/settlement + per-tool totals and spend-log updates.
js/README.md Documents tool spend under the shared ceiling for the TS package.
js/package.json Bumps JS package version.
js/package-lock.json Updates lockfile version metadata to match the bumped package version.
examples/tool_budget.py New example demonstrating reserve/settle + record_tool + attribution.
CHANGELOG.md Adds release notes for the tool-spend feature and behavior changes.
Files not reviewed (1)
  • js/package-lock.json: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CHANGELOG.md Outdated
Comment thread src/floe_guard/guard.py
Comment thread src/floe_guard/guard.py
Comment thread js/src/guard.ts
Comment thread js/src/guard.ts
@achris7

achris7 commented Jul 18, 2026

Copy link
Copy Markdown
Member

a few comments to check @shivamfloe

@achris7 achris7 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

see feedbacks

Signed-off-by: shivamfloe <shivam@floelabs.xyz>

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

11-14: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clarify that paid-tool hard stops require pre-call reservation.

record_tool() is post-hoc and cannot block the call that already ran. Precise pre-call enforcement requires reserve_tool(...) followed by settle_tool(...) (or an adapter that performs that flow). The current intro may lead users to use record_tool() alone while assuming the paid call is protected.

Proposed wording
- next LLM or paid tool call
+ next LLM call or paid tool call when protected with reserve_tool()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 11 - 14, Clarify the README introduction that
paid-tool hard stops require reserving budget before the call and settling
afterward, using reserve_tool(...) and settle_tool(...) or an adapter that
performs both; distinguish this from record_tool(), which only records completed
calls and cannot prevent an already-started call.
♻️ Duplicate comments (1)
src/floe_guard/guard.py (1)

412-422: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Numeric reservation handles are reusable and can release unrelated in-flight holds.

As previously flagged, the tool reservation APIs continue to use raw numbers as reservation handles. This allows an unrelated in-flight hold to be released, or a handle to be reused to decrement the reserved total multiple times, breaking the budget cap.

  • src/floe_guard/guard.py#L412-L422: Replace numeric reservation tracking with opaque, single-use reservation IDs for reserve_tool and settle_tool.
  • js/src/guard.ts#L350-L362: Implement the same single-use reservation-token contract here for parity.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/floe_guard/guard.py` around lines 412 - 422, The tool reservation APIs
currently use numeric handles, allowing unrelated or reused handles to release
holds multiple times. Update reserve_tool and settle_tool in
src/floe_guard/guard.py (lines 412-422) to generate opaque, single-use
reservation IDs, track each ID to its reservation, and reject unknown or
already-settled IDs. Apply the same single-use reservation-token contract to
reserve_tool and settle_tool in js/src/guard.ts (lines 350-362) for parity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@README.md`:
- Around line 11-14: Clarify the README introduction that paid-tool hard stops
require reserving budget before the call and settling afterward, using
reserve_tool(...) and settle_tool(...) or an adapter that performs both;
distinguish this from record_tool(), which only records completed calls and
cannot prevent an already-started call.

---

Duplicate comments:
In `@src/floe_guard/guard.py`:
- Around line 412-422: The tool reservation APIs currently use numeric handles,
allowing unrelated or reused handles to release holds multiple times. Update
reserve_tool and settle_tool in src/floe_guard/guard.py (lines 412-422) to
generate opaque, single-use reservation IDs, track each ID to its reservation,
and reject unknown or already-settled IDs. Apply the same single-use
reservation-token contract to reserve_tool and settle_tool in js/src/guard.ts
(lines 350-362) for parity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e96a8f9f-a745-4cff-a28e-3869d514cc03

📥 Commits

Reviewing files that changed from the base of the PR and between 442c07b and 789f427.

⛔ Files ignored due to path filters (1)
  • js/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • README.md
  • js/package.json
  • js/src/guard.ts
  • js/test/tool-costs.test.ts
  • src/floe_guard/__init__.py
  • src/floe_guard/guard.py
  • tests/test_tool_costs.py

@shivamfloe
shivamfloe merged commit 69990df into main Jul 21, 2026
9 of 10 checks passed
@shivamfloe
shivamfloe deleted the feat/tool-tracking branch July 21, 2026 15:04
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.

4 participants