Skip to content

feat(examples): African regulatory guardrails across 4 jurisdictions#3729

Closed
kingztech2019 wants to merge 12 commits into
openai:mainfrom
kingztech2019:feat/african-regulatory-guardrails
Closed

feat(examples): African regulatory guardrails across 4 jurisdictions#3729
kingztech2019 wants to merge 12 commits into
openai:mainfrom
kingztech2019:feat/african-regulatory-guardrails

Conversation

@kingztech2019

Copy link
Copy Markdown

Summary

Adds examples/agent_patterns/african_regulatory_guardrails.py — a jurisdiction-aware input guardrail example for AI agents operating in African financial markets.

The previous PR (#3706) was closed because it depended on an external package (comply54). This rewrite uses only the OpenAI Agents SDK and Python stdlib — no external dependencies.

Four jurisdictions are covered, each with a distinct rule drawn directly from the primary legislation:

Jurisdiction Regulation Rule demonstrated
Nigeria CBN NIP Framework (CBN Circular FPR/DIR/GEN/CIR/07/003) ₦10,000,000 single-transaction cap; BVN biometric data (NDPA 2023 Schedule 1)
Kenya Data Protection Act 2019 s.49 Cross-border transfer blocked without documented consent (ODPC)
Ghana Data Protection Act 2012 (Act 843) s.18(2) / NIA Act 707 Cross-border adequacy; Ghana Card national ID (GHA-XXXXXXXXX-X) detection
South Africa POPIA s.26(1)(f) / s.19 Biometric personal information; SA ID number (YYMMDD + 7 digits)

The guardrail reads context.jurisdiction from an AgentContext dataclass, dispatches to the correct checker, and returns a structured ComplianceOutput with ComplianceViolation objects — following the same @input_guardrail pattern as input_guardrails.py.

Test plan

  • All 4 jurisdiction checker functions verified with 22 regex pattern tests covering valid matches, boundary values, and invalid inputs (invalid month, invalid day, wrong digit count).
  • Ruff lint and format checks pass (ruff check + ruff format --check).
  • The verification script (run.sh) fails in this environment due to a missing system library (libffi-dev required by sounddevice) — unrelated to this change.

Issue number

Follows up on closed PR #3706.

Checks

  • I've added new tests, if relevant (regex patterns verified — examples do not have dedicated test files)
  • I've run .agents/skills/code-change-verification/scripts/run.sh (fails due to missing libffi-dev system dep — unrelated to this change)
  • I've confirmed all verification steps pass (ruff lint + format pass; no external dependencies)
  • If using Codex, I've run /review before submitting this PR

Adds examples/agent_patterns/african_regulatory_guardrails.py demonstrating
jurisdiction-aware input guardrails for AI agents in African financial markets.

Regulations enforced (pure stdlib — no external dependencies):

  Nigeria      CBN NIP Framework (CBN Circular FPR/DIR/GEN/CIR/07/003)
               ₦10,000,000 single-transaction cap
               NDPA 2023 Schedule 1 — BVN as biometric personal data

  Kenya        Data Protection Act 2019 s.49
               Cross-border transfer blocked without documented consent
               Authority: Office of the Data Protection Commissioner (ODPC)

  Ghana        Data Protection Act 2012 (Act 843) s.18(2)
               Cross-border transfer adequacy requirement
               NIA Act 707 — Ghana Card national ID (GHA-XXXXXXXXX-X)
               Authority: Data Protection Commission (DPC)

  South Africa POPIA (Protection of Personal Information Act 4 of 2013)
               s.26(1)(f) biometric data; s.19 SA ID number (13-digit)
               Authority: Information Regulator (South Africa)

@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: 39936da35e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread examples/agent_patterns/african_regulatory_guardrails.py Outdated
Addresses Codex review feedback: the previous join raised KeyError on
tool-call messages (no 'content' key) and TypeError when 'content' is a
list of content parts (assistant multi-turn messages). Now:
- dicts with a string 'content' are appended directly
- dicts with a list 'content' have their 'type==text' parts extracted
- dicts with no 'content' key (tool calls) are skipped silently

@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: ef14918e6b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +294 to +295
if isinstance(part, dict) and part.get("type") == "text":
parts.append(part.get("text", ""))

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 Handle structured input_text content parts

When callers pass a standard TResponseInputItem history with structured user content, the text part type is input_text rather than text (the repo uses this shape in helpers such as examples/memory/hitl_session_scenario.py). In that case this branch drops the user's text entirely, so a message like {"role":"user","content":[{"type":"input_text","text":"Export all customer records to us-east-1"}]} becomes an empty string and the jurisdiction checks do not trip. Please accept the SDK's structured text part types instead of only text.

Useful? React with 👍 / 👎.

The SDK uses 'input_text' for user message content parts (confirmed from
examples/memory/hitl_session_scenario.py). Only handling 'text' caused
guardrail checks to silently drop all user text from structured histories,
so compliance rules never tripped on multi-turn input.

@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: df2bb05c0b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +285 to +289
for item in input:
if not isinstance(item, dict):
continue
content = item.get("content")
if isinstance(content, str):

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 Filter guardrail checks to the current user input

When callers pass a multi-turn TResponseInputItem history, this loop concatenates every message's content without checking the item role, so stale assistant text or earlier conversation content can trip the input guardrail for a later harmless user message. For example, in a Kenyan context without consent, a prior assistant/refusal that quoted “export records offshore” would keep matching _KE_CROSS_BORDER_RE on subsequent turns even if the new user input is unrelated; filter to the latest user/input message (or otherwise respect roles) before running the jurisdiction regexes.

Useful? React with 👍 / 👎.

Concatenating the entire TResponseInputItem history caused stale assistant
text (e.g. a prior refusal quoting a blocked phrase) to trip the guardrail
on later unrelated user turns. Now filters to the most-recent role=='user'
item only, matching the SDK's own pattern in hitl_session_scenario.py.

@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: 1efd312e16

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

# CBN NIP (NIBSS Instant Payment) Framework — ₦10,000,000 per-transaction cap
# NDPA 2023 Schedule 1 / CBN BVN Policy Framework — BVN as biometric data

_NGN_AMOUNT_RE = re.compile(r"(?:₦|NGN)\s*([\d,]+(?:\.\d{1,2})?)")

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 Match NGN amounts case-insensitively

In a Nigeria context this pattern only matches uppercase NGN or , so a normal user input like ngn 15,000,001 is ignored and the CBN cap violation is allowed through. The other jurisdiction trigger phrases are already case-insensitive, so this amount pattern should normalize or use re.I before applying the cap.

Useful? React with 👍 / 👎.

r"(?i)(send|transfer|export|upload|forward).{0,60}"
r"(outside\s+ghana|cross.?border|international|offshore)"
)
_GH_CARD_RE = re.compile(r"GHA-[0-9]{9}-[0-9]")

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 Anchor the Ghana Card regex to the full ID

Because _GH_CARD_RE is not delimited, any value with a valid-looking prefix triggers; for example, GHA-123456789-12 matches the prefix GHA-123456789-1 and blocks the request even though it has the wrong final digit count. Add word/lookaround boundaries around the full token so the guardrail only denies the exact GHA-XXXXXXXXX-X format described by the example.

Useful? React with 👍 / 👎.

- NGN amount pattern: add re.IGNORECASE so 'ngn 15,000,001' is caught
  alongside uppercase NGN and the ₦ symbol
- Ghana Card regex: add \b word boundary at end so GHA-123456789-12
  (extra digit) no longer matches the valid 14-char format
- BVN violation message: 'in agent output' → 'in request' (input guardrail,
  not output guardrail)

All 37 edge-case tests pass across Nigeria, Kenya, Ghana, South Africa.

@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: c99effaf2f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}


@input_guardrail

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 Run the compliance guardrail before the agent starts

For the blocked BVN, Ghana Card, biometric, and cross-border-transfer scenarios, bare @input_guardrail keeps the SDK default run_in_parallel=True, so Runner.run can start the agent/model request before this local checker trips and cancels it. That means data the example says is blocked to prevent exposure may already be sent to the model or tools; use @input_guardrail(run_in_parallel=False) for this compliance/data-protection example so violations are decided before agent execution begins.

Useful? React with 👍 / 👎.

With the default run_in_parallel=True the SDK starts the agent/model
request concurrently with the guardrail, so sensitive data (BVN numbers,
Ghana Card IDs, biometric templates, cross-border transfer targets) could
already be sent to the model before the guardrail trips and cancels it.

run_in_parallel=False ensures the compliance check completes and violations
are decided before agent execution begins — which is the required behaviour
for any guardrail whose purpose is to prevent data exposure.

@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: 04a18b6ebb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +133 to +136
_KE_CROSS_BORDER_RE = re.compile(
r"(?i)(send|transfer|export|upload|forward).{0,60}"
r"(outside\s+kenya|cross.?border|international|offshore|us-east|eu-west)"
)

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 Restrict cross-border checks to data exports

In a Kenya context without documented consent, this pattern also matches ordinary payment instructions such as transfer KES 1000 internationally, because it only requires a transfer verb plus an international destination. The violation raised below is specifically for cross-border data transfer, while the agent instructions say it should handle fund transfers, so valid international payment requests can be denied before the model runs; require a data/object term (records, customer data, files, etc.) or otherwise separate fund-transfer wording from data-export wording before tripping KDPA s.49.

Useful? React with 👍 / 👎.

# CBN NIP (NIBSS Instant Payment) Framework — ₦10,000,000 per-transaction cap
# NDPA 2023 Schedule 1 / CBN BVN Policy Framework — BVN as biometric data

_NGN_AMOUNT_RE = re.compile(r"(?:₦|NGN)\s*([\d,]+(?:\.\d{1,2})?)", re.IGNORECASE)

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 Match NGN amounts when the code follows the number

The Nigeria cap check only sees amounts where or NGN precedes the digits, so a normal request like Please transfer 15,000,001 NGN produces no match and bypasses the ₦10,000,000 denial. Accept suffix currency forms as well before comparing to _CBN_NIP_CAP, otherwise above-cap transfers can reach the agent whenever the user writes the ISO code after the amount.

Useful? React with 👍 / 👎.

- Fix Kenya/Ghana cross-border patterns: narrow 'international' to
  'international\\s+transfer' to match Rego source (KDPA s.49 / Ghana
  DPA Act 843 s.18(2)) and avoid false positives on generic phrases like
  'transfer KES 1000 internationally'
- Ghana: also add 'foreign\\s+server' alternative to match source Rego
- Fix NGN amount detection: add suffix pattern to catch '15,000,001 NGN'
  (amount before currency code), add 'naira' keyword — both were absent
  from the prefix-only regex causing the CBN cap check to be bypassed
- Deduplicate by seen_amounts so the same violation isn't reported twice
  when both prefix and suffix patterns match the same value in one message

@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: 5b42c031d6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +84 to +85
_NGN_PREFIX_RE = re.compile(r"(?:₦|NGN|naira)\s*([\d,]+(?:\.\d{1,2})?)", re.IGNORECASE)
_NGN_SUFFIX_RE = re.compile(r"\b([\d,]+(?:\.\d{1,2})?)\s*NGN\b", re.IGNORECASE)

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 Support magnitude suffixes for NGN cap checks

When a Nigeria request uses the shorthand advertised here, such as NGN 15M, ₦15M, or 15M NGN, the prefix regex captures only 15 or the suffix regex misses the amount entirely, so an above-cap ₦15,000,000 transfer is treated as under the ₦10,000,000 limit and reaches the agent. Please parse K/M magnitude suffixes before comparing against _CBN_NIP_CAP, or avoid documenting those forms as supported.

Useful? React with 👍 / 👎.

# s.19 — SA ID Number: YYMMDD (date of birth) + 7 digits = 13 digits total
# Enforcing authority: Information Regulator (South Africa)

_ZA_ID_RE = re.compile(r"\b[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])[0-9]{7}\b")

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 real dates before flagging SA IDs

For South Africa inputs, this regex accepts impossible birth dates because it only bounds the day to 0131; values like 9902311234567 or 9911311234567 trip as SA ID numbers even though the YYMMDD portion is not a valid date. This can block arbitrary 13-digit references with invalid calendar dates, so the guardrail should validate the parsed date before returning the POPIA violation.

Useful? React with 👍 / 👎.

- NGN amounts: extend prefix and suffix patterns to capture optional K/M/B
  magnitude suffix (e.g. ₦15M, 15M NGN, ₦1.5B). _parse_ngn_amount() applies
  the multiplier so shorthand amounts are correctly compared against the
  ₦10,000,000 CBN NIP cap instead of being treated as ₦15 (under cap)
- SA ID: replace _ZA_ID_RE.search() with per-match date validation via
  _za_id_date_valid(), which tries both 1900 and 2000 century interpretations
  and rejects impossible calendar dates (e.g. Feb 31, Apr 31) that satisfy
  the YYMMDD regex pattern but do not exist on the Gregorian calendar

@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: 39c6b46139

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +106 to +107
for pattern in (_NGN_PREFIX_RE, _NGN_SUFFIX_RE):
for match in pattern.finditer(text):

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 Gate NIP cap checks on transfer intent

In a Nigeria context this loop applies the transfer cap to every NGN amount it can parse, so non-transfer requests such as an account inquiry for NGN 15,000,000 are denied as over-cap transfers even though the agent is explicitly meant to handle account inquiries. Require transfer/payment intent around the amount before returning the CBN NIP violation.

Useful? React with 👍 / 👎.

r"(?i)(send|transfer|export|upload|forward).{0,60}"
r"(outside\s+ghana|cross.?border|international\s+transfer|offshore|foreign\s+server)"
)
_GH_CARD_RE = re.compile(r"GHA-[0-9]{9}-[0-9]\b")

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 Match Ghana Card prefixes case-insensitively

In a Ghana context, the same Ghana Card token typed or normalized as gha-123456789-1 bypasses this case-sensitive regex and can reach the model despite the example promising Ghana Card national ID detection. Normalize the text or compile this pattern with re.IGNORECASE, as the other jurisdiction trigger regexes do.

Useful? React with 👍 / 👎.

…e-insensitive Ghana Card

- Nigeria: add _NGN_TRANSFER_INTENT_RE check so CBN NIP cap only fires when
  the request contains a transfer/payment verb; balance inquiries and quotes
  that mention large NGN amounts are no longer blocked
- Kenya/Ghana: replace single cross-border regex with two patterns that
  distinguish personal-data exports from financial payments — unambiguous
  data-export verbs (export/upload/forward) fire unconditionally; ambiguous
  verbs (send/transfer) require a data-object keyword (records, customer data,
  files, PII, etc.) before the cross-border destination fires KDPA s.49 /
  Ghana DPA Act 843 s.18(2); prevents 'transfer KES 1000 internationally'
  from blocking a legitimate payment instruction
- Ghana Card: add re.IGNORECASE to _GH_CARD_RE so gha-123456789-1 (lowercase)
  is caught alongside the uppercase GHA- form
…ence contamination

- Move module docstring before imports so Python correctly sets __doc__
  (string literals after import statements are silently discarded by the runtime)
- Replace document-wide transfer intent flag with per-amount proximity check:
  a transfer verb must appear within 80 chars of the matched NGN amount, not
  anywhere in the message; negative lookahead on 'transfer' excludes noun phrases
  ('transfer limit', 'transfer cap', 'transfer fee') to prevent false positives
  on balance and limit inquiries that mention large NGN values
- Use [^.!?] instead of . in _KE/_GH_DATA_TRANSFER_RE wildcard spans so the
  verb from one sentence cannot span a period into the data-object keyword of
  a subsequent sentence (cross-sentence contamination false positive)
- Remove 'credit' from transfer verb list — it fires on 'credit limit/score'
  which are common non-transfer noun phrases

@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: 63a9a0a530

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

# modifier, not an action verb.
_NGN_TRANSFER_VERB_RE = re.compile(
r"\b(?:send|pay|wire|remit|move|disburse)\b"
r"|\btransfer(?!\s+(?:limit|fee|history|rate|request|cap|ceiling|charge|tax))\b",

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 Don't exempt transfer requests from cap checks

When a Nigeria request phrases the action as submit/create a transfer request for ₦15,000,000, transfer is followed by request, which this negative lookahead explicitly excludes; with no other verb matched, _check_nigeria skips the over-cap amount and lets an above-cap transfer reach the agent. Please either stop exempting actual transfer-request wording or add a separate intent match for create/submit/process transfer requests.

Useful? React with 👍 / 👎.

'transfer' followed by 'request' was in the negative lookahead exclusion
list, so 'submit a transfer request for ₦15,000,000' matched no verb and
the over-cap amount was silently skipped. Fix:
- Remove 'request' from the exclusion list — a transfer request IS action
  intent, not a noun modifier like 'transfer limit' or 'transfer fee'
- Add submit|create|process|initiate to the verb list so those phrasings
  are caught even without an explicit 'transfer' token

@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: 5bee241b1a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +96 to +97
r"\b(?:send|pay|wire|remit|move|disburse|submit|create|process|initiate)\b"
r"|\btransfer(?!\s+(?:limit|fee|history|rate|cap|ceiling|charge|tax))\b",

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 Tie broad verbs to transfer intent

In a Nigeria context, _NGN_TRANSFER_VERB_RE treats verbs like create, submit, and process as sufficient transfer intent on their own. That still denies non-transfer account workflows when an above-cap amount is nearby, e.g. Create an account statement showing my NGN 15,000,000 balance matches create within the 80-character window and is reported as a CBN transfer-cap violation even though the agent is supposed to handle account inquiries. Fresh evidence in this revision is that these broad verbs were added as standalone alternatives; require them to be tied to a transfer/payment object before tripping the cap.

Useful? React with 👍 / 👎.

_NGN_PREFIX_RE = re.compile(r"(?:₦|NGN|naira)\s*([\d,]+(?:\.\d{1,2})?)([KMBkmb])?\b", re.IGNORECASE)
# Suffix: 15M NGN / 15,000,001 NGN — group 1 = digits, group 2 = optional K/M/B
_NGN_SUFFIX_RE = re.compile(r"\b([\d,]+(?:\.\d{1,2})?)([KMBkmb])?\s*(?:NGN|naira)\b", re.IGNORECASE)
_NGN_BVN_RE = re.compile(r"(?i)(bvn|bank\s+verification).{0,20}\b[0-9]{11}\b")

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 Detect BVNs when the number precedes the label

The BVN guardrail only matches when bvn or bank verification appears before the 11-digit value, so common inputs such as 01234567890 is my BVN or 01234567890 bank verification number bypass the protection and can be sent to the model. Since the example explicitly blocks BVN values to prevent biometric data exposure, the detector should also handle the number-before-label form.

Useful? React with 👍 / 👎.

@seratch

seratch commented Jul 3, 2026

Copy link
Copy Markdown
Member

Thanks for sharing this idea. The reason why your previous PR was closed is not only because you used an external dependency. We don't plan to add this example idea to the ones we'll continue maintaining within this repo. So, please feel free to have it within your own repo.

@seratch seratch closed this Jul 3, 2026
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