Skip to content

Examples/cbam calculator#570

Closed
Subhajitdas99 wants to merge 5 commits into
GetBindu:mainfrom
Subhajitdas99:examples/cbam-calculator
Closed

Examples/cbam calculator#570
Subhajitdas99 wants to merge 5 commits into
GetBindu:mainfrom
Subhajitdas99:examples/cbam-calculator

Conversation

@Subhajitdas99
Copy link
Copy Markdown
Contributor

@Subhajitdas99 Subhajitdas99 commented Jun 1, 2026

Summary

  • Problem: EU importers of iron/steel, aluminium, cement, fertilizers, hydrogen, and electricity have faced direct CBAM financial liability since 1 January 2026 with no affordable tool to calculate their exposure.
  • Why it matters: Getting CBAM wrong means blocked shipments, fines, and unexpected carbon costs that wipe out margins. SMBs currently rely on expensive consultants or guess.
  • What changed: Added examples/cbam-calculator/ — an Agno + OpenRouter agent that checks CBAM applicability, applies the 50-tonne exemption threshold, estimates certificate costs using EU ETS price, and generates a compliance checklist.
  • What did NOT change: No changes to core Bindu framework, server, extensions, or any existing examples.

Change Type

  • Feature

Scope

  • Documentation

Linked Issue/PR

Related: Bindu trade compliance roadmap (Discord, 29 May 2026). Second agent in the compliance toolchain after #569 (HS Code Classifier).

User-Visible / Behavior Changes

New example agent at examples/cbam-calculator/. Requires OPENROUTER_API_KEY. No changes to existing behaviour.

Security Impact

  • New permissions/capabilities? No
  • Secrets/credentials handling changed? No
  • New/changed network calls? Yes — agent calls OpenRouter API at runtime
  • Database schema/migration changes? No
  • Authentication/authorization changes? No
  • Risk + mitigation: API key loaded from environment variable only. # pragma: allowlist secret added to suppress false-positive detection.

Verification

Environment

  • OS: Windows 10
  • Python version: 3.12
  • Storage backend: In-memory
  • Scheduler backend: In-memory

Steps to Test

  1. cd examples/cbam-calculator
  2. cp .env.example .env and set OPENROUTER_API_KEY
  3. python cbam_calculator.py
  4. Send: Calculate CBAM cost for 200 tonnes of aluminium from Turkey

Expected Behavior

  • Agent starts and registers DID
  • CBAM Compliance Skill v1.0.0 loads
  • Returns CBAM APPLICABILITY / EXEMPTION CHECK / COST ESTIMATE / COMPLIANCE REQUIREMENTS / DOCUMENTATION CHECKLIST / KEY RISKS

Actual Behavior

Matches expected. Correctly returned:

  • CN code 7601 for aluminium
  • 200t > 50t threshold → full compliance required
  • 200t × 6.36 tCO2e/t = 1,272 tCO2e × €65 = €82,680 estimated CBAM cost
  • Full compliance checklist and key risks
  • DID signature on every response

Evidence

  • Test output / logs

Human Verification

  • Verified: Agent starts, skill loads, DID registered, full CBAM calculation returned end-to-end
  • Edge cases: Below 50 tonnes → exempt status returned. Non-covered sector → agent says so clearly
  • Not verified: Accuracy against live EU ETS price (agent uses ~€65 approximation and directs user to Ember for live price)

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Database migration needed? No

Failure Recovery

Remove examples/cbam-calculator/ — self-contained, no framework changes.

Risks and Mitigations

  • Risk: EU ETS price fluctuates — cost estimate may differ from actual

Checklist

  • Pre-commit hooks pass
  • Documentation updated
  • Security impact assessed
  • Human verification completed
  • Backward compatibility considered

Summary by CodeRabbit

  • New Features

    • Added a CBAM Carbon Calculator example agent with a compliance skill for sector applicability, exemption checks, cost estimates, and formatted outputs.
  • Documentation

    • Added a comprehensive README with setup, usage examples, key compliance dates, and a legal disclaimer.
    • Added an environment template including an API key placeholder.
  • Chores

    • Minor project configuration tidy-up (dependency ordering).

EU CBAM agent that calculates carbon border adjustment costs for importers
of iron/steel, aluminium, cement, fertilizers, hydrogen and electricity.
Covers applicability check, 50-tonne exemption threshold, cost estimate
using EU ETS price, compliance requirements and documentation checklist.
Verified locally: 200t aluminium from Turkey = 82,680 EUR CBAM cost.
Part of Bindu's trade compliance toolchain.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a CBAM (Carbon Border Adjustment Mechanism) calculator example: env placeholder, comprehensive README, a new agent script with INSTRUCTIONS and OpenRouter-configured Agent, Bindu config and handler, and a CBAM compliance skill YAML.

Changes

CBAM Calculator Example Agent

Layer / File(s) Summary
Environment setup and documentation
examples/cbam-calculator/.env.example, examples/cbam-calculator/README.md, pyproject.toml
Adds OPENROUTER_API_KEY placeholder with allowlist pragma to .env.example; introduces a full README for the CBAM example; reorders duckduckgo-search entry and adds a blank line in pyproject.toml (no functional dependency change).
Agent core and instructions
examples/cbam-calculator/cbam_calculator.py
Adds module header and imports with load_dotenv(), a detailed INSTRUCTIONS prompt template, and creates an Agent configured to use OpenRouter with the API key from env.
Bindu framework integration
examples/cbam-calculator/cbam_calculator.py
Adds config dict declaring identity/capabilities/skills and deployment settings; implements handler(messages) that validates the latest user message, runs agent.run(input=messages), handles exceptions, and a __main__ entrypoint to start the Bindu app.
CBAM compliance skill configuration
examples/cbam-calculator/skills/cbam-compliance-skill/skill.yaml
Introduces a full skill YAML with metadata, supported sectors and exempt countries, regulatory timeline, example scenarios, capability definitions (applicability, exemption threshold, cost calculation), output format, transport settings, and a legal disclaimer referencing EU Regulation 2023/956.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • GetBindu/Bindu#483: Adds a similar example agent using Agent with OPENROUTER_API_KEY and a typed handler(messages: list[dict[str, str]]) pattern for Bindu integration.

Suggested reviewers

  • Paraschamoli
  • raahulrahl

Poem

🐰 I hop through docs and env with cheer,
A carbon calculator now appears,
OpenRouter hums to answer the call,
Bindu wraps it neatly for one and all,
Regulations cited — compliance near!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive Title is vague and generic, using only 'Examples/cbam calculator' without clarifying the main purpose (adding a new CBAM carbon calculator agent example). Revise title to be more specific, e.g., 'Add CBAM carbon calculator example agent' to clearly indicate this adds a new example for CBAM compliance calculations.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed PR description is comprehensive, well-structured, and addresses all required sections from the template with clear problem statement, change summary, security impact, verification steps, and human verification.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
examples/cbam-calculator/cbam_calculator.py (2)

185-186: ⚡ Quick win

Prefer get_logger(__name__) over print() for startup output.

♻️ Proposed change
+from bindu.utils.logging import get_logger
+
+logger = get_logger(__name__)
+
 if __name__ == "__main__":
-    print("🌍 CBAM Carbon Calculator running at http://localhost:3773")
-    print("♻️  Example: Calculate CBAM cost for 200 tonnes of aluminium from Turkey")
+    logger.info("🌍 CBAM Carbon Calculator running at http://localhost:3773")
+    logger.info("♻️  Example: Calculate CBAM cost for 200 tonnes of aluminium from Turkey")
     bindufy(config, handler)

As per coding guidelines: "Use get_logger(__name__) from bindu/utils/logging.py instead of print() for logging".

🤖 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 `@examples/cbam-calculator/cbam_calculator.py` around lines 185 - 186, Replace
the two startup print() calls with a module logger: import and instantiate
logger = get_logger(__name__) from bindu.utils.logging and replace the prints in
cbam_calculator.py (the two lines printing startup URL and example) with
logger.info(...) calls using the same messages so startup output follows the
project's logging conventions.

173-174: ⚡ Quick win

Bindufy already normalizes Agno RunOutput via .content, so this isn’t a critical bug.

manifest_worker runs ResultProcessor.normalize_result(), which returns result.content when the handler returns an object with a .content attribute—so return result should work with agno’s RunOutput. Returning result.content (or result.to_dict()["content"]) is still optional for clarity/consistency with the bindufy docs.

🤖 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 `@examples/cbam-calculator/cbam_calculator.py` around lines 173 - 174, The
handler currently returns the raw object from agent.run (result) which relies on
downstream normalization; to make the output explicit and consistent with
Bindufy docs, change the return to return the RunOutput's content (e.g., use
result.content or result.to_dict()["content"]) so
manifest_worker.ResultProcessor.normalize_result() still receives the expected
string payload; locate the agent.run call in the function that invokes the agent
(agent.run) and replace the final return of result with returning its .content.
🤖 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 `@examples/cbam-calculator/cbam_calculator.py`:
- Around line 166-171: The guard computes query from user_messages[-1] but never
uses it when invoking the agent, so align the inputs: either use the extracted
query when running the agent (pass [ {"role": "user", "content": query} ] or
equivalent to agent.run) or remove the query variable and validate directly
against messages/user_messages; update the code paths around query,
user_messages, messages, and the agent.run call so the same data is validated
and passed to the agent.

In `@pyproject.toml`:
- Line 67: Remove the "duckduckgo-search>=8.1.1" entry from the core
[project.dependencies] block in pyproject.toml and ensure it remains only in the
optional [project.optional-dependencies].agents group; verify the CBAM example
(examples/cbam-calculator/cbam_calculator.py) continues to import only agno,
OpenRouter and python-dotenv (and not DuckDuckGoTools) so runtime installs are
not forced to include duckduckgo-search.

---

Nitpick comments:
In `@examples/cbam-calculator/cbam_calculator.py`:
- Around line 185-186: Replace the two startup print() calls with a module
logger: import and instantiate logger = get_logger(__name__) from
bindu.utils.logging and replace the prints in cbam_calculator.py (the two lines
printing startup URL and example) with logger.info(...) calls using the same
messages so startup output follows the project's logging conventions.
- Around line 173-174: The handler currently returns the raw object from
agent.run (result) which relies on downstream normalization; to make the output
explicit and consistent with Bindufy docs, change the return to return the
RunOutput's content (e.g., use result.content or result.to_dict()["content"]) so
manifest_worker.ResultProcessor.normalize_result() still receives the expected
string payload; locate the agent.run call in the function that invokes the agent
(agent.run) and replace the final return of result with returning its .content.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ca3ae039-ac6c-406b-aa50-3fcacad7d5dc

📥 Commits

Reviewing files that changed from the base of the PR and between 682a19c and 17dabeb.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • examples/cbam-calculator/.env.example
  • examples/cbam-calculator/README.md
  • examples/cbam-calculator/cbam_calculator.py
  • examples/cbam-calculator/skills/cbam-compliance-skill/skill.yaml
  • pyproject.toml

Comment on lines +166 to +171
query = user_messages[-1].get("content", "").strip()
if not query:
return (
"Empty query. Please describe your import situation, e.g. "
"'Calculate CBAM cost for 200 tonnes of aluminium from Turkey'"
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Minor: query is validated but never used.

The non-empty query is computed for the empty-input guard but the agent is run on the full messages list, so the extracted query is otherwise unused. Functionally fine; flagging for clarity since the guard and the run input diverge.

🤖 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 `@examples/cbam-calculator/cbam_calculator.py` around lines 166 - 171, The
guard computes query from user_messages[-1] but never uses it when invoking the
agent, so align the inputs: either use the extracted query when running the
agent (pass [ {"role": "user", "content": query} ] or equivalent to agent.run)
or remove the query variable and validate directly against
messages/user_messages; update the code paths around query, user_messages,
messages, and the agent.run call so the same data is validated and passed to the
agent.

Comment thread pyproject.toml Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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)
examples/cbam-calculator/cbam_calculator.py (1)

166-171: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

logger is undefined — this will raise NameError at runtime.

Line 167 calls logger.debug(...) but logger is never imported or instantiated. This will crash when the handler receives a valid query.

🐛 Proposed fix: Add logger import and instantiation
 import os
 
+from bindu.utils.logging import get_logger
 from agno.agent import Agent
 from agno.models.openrouter import OpenRouter
 from bindu.penguin.bindufy import bindufy
 from dotenv import load_dotenv
 
 load_dotenv()
+
+logger = get_logger(__name__)

As per coding guidelines: "Use get_logger(__name__) from bindu/utils/logging.py for logging".

🤖 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 `@examples/cbam-calculator/cbam_calculator.py` around lines 166 - 171, The code
calls logger.debug(...) in the handler where it computes query from
user_messages but never defines logger, causing a NameError; import get_logger
from bindu.utils.logging and instantiate logger = get_logger(__name__) at the
module level (with the other imports) so the logger symbol used around the
query/user_messages logic is defined; verify the instantiation is above the
function that references logger.
🧹 Nitpick comments (1)
examples/cbam-calculator/cbam_calculator.py (1)

184-187: 💤 Low value

Consider using logger for startup messages per coding guidelines.

The startup messages use print(). While this is common for CLI banners, the coding guidelines specify using get_logger(__name__) instead of print().

♻️ Optional: Use logger for consistency
 if __name__ == "__main__":
-    print("🌍 CBAM Carbon Calculator running at http://localhost:3773")
-    print("♻️  Example: Calculate CBAM cost for 200 tonnes of aluminium from Turkey")
+    logger.info("🌍 CBAM Carbon Calculator running at http://localhost:3773")
+    logger.info("♻️  Example: Calculate CBAM cost for 200 tonnes of aluminium from Turkey")
     bindufy(config, handler)

As per coding guidelines: "Use get_logger(__name__) from bindu/utils/logging.py for logging, not print()".

🤖 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 `@examples/cbam-calculator/cbam_calculator.py` around lines 184 - 187, Startup
messages use print() instead of the project logger; import get_logger from
bindu.utils.logging, create a logger = get_logger(__name__) near the module top
if not present, and replace the two print() calls in the if __name__ ==
"__main__": block with logger.info(...) (keeping the same message strings)
before calling bindufy(config, handler); ensure no other call sites rely on
stdout prints.
🤖 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 `@examples/cbam-calculator/cbam_calculator.py`:
- Around line 166-171: The code calls logger.debug(...) in the handler where it
computes query from user_messages but never defines logger, causing a NameError;
import get_logger from bindu.utils.logging and instantiate logger =
get_logger(__name__) at the module level (with the other imports) so the logger
symbol used around the query/user_messages logic is defined; verify the
instantiation is above the function that references logger.

---

Nitpick comments:
In `@examples/cbam-calculator/cbam_calculator.py`:
- Around line 184-187: Startup messages use print() instead of the project
logger; import get_logger from bindu.utils.logging, create a logger =
get_logger(__name__) near the module top if not present, and replace the two
print() calls in the if __name__ == "__main__": block with logger.info(...)
(keeping the same message strings) before calling bindufy(config, handler);
ensure no other call sites rely on stdout prints.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 875e7b9e-446a-48d6-b901-731e058d1a8a

📥 Commits

Reviewing files that changed from the base of the PR and between 02c583a and dea69cb.

📒 Files selected for processing (1)
  • examples/cbam-calculator/cbam_calculator.py

@Paraschamoli
Copy link
Copy Markdown
Member

hey @Subhajitdas99 also this pr

@Paraschamoli
Copy link
Copy Markdown
Member

i am closing it

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.

2 participants