Beemer Claude Fable 5 commited on
Commit
33bb287
·
1 Parent(s): 763ef99

Wire the s. 36 screening tools into the agentic loop

Browse files

Declares canlex_us_disposition, canlex_us_equivalency and
canlex_rehabilitation to Gemini, adds the three-step US-record screening
flow to the system instruction, and gives each tool a call-trace line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +118 -4
app.py CHANGED
@@ -175,11 +175,109 @@ TOOL_DECLARATIONS = [
175
  "required": ["case_url"],
176
  },
177
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  ]
179
 
180
- # The three tools whose MCP signature wraps arguments under a single 'params'
181
- # object. canlex_list_acts takes none and is handled separately in _run_tool.
182
- _PARAMS_WRAPPED = {"canlex_search_legislation", "canlex_get_section", "canlex_case"}
 
 
183
 
184
 
185
  # --- System prompt ------------------------------------------------------------
@@ -187,7 +285,7 @@ _PARAMS_WRAPPED = {"canlex_search_legislation", "canlex_get_section", "canlex_ca
187
  SYSTEM_INSTRUCTION = """\
188
  You are CanLex Web, a Canadian legal-research assistant. A member of the public \
189
  has asked the legal question shown below through a web form. Answer it by \
190
- agentically using the four CanLex tools to retrieve primary sources, then \
191
  compose a clear, well-organised answer grounded entirely in what those tools \
192
  return.
193
 
@@ -199,6 +297,13 @@ bears on the question but is not reproduced, call canlex_get_section or \
199
  canlex_search_legislation again to fetch it. Do not guess its contents.
200
  - For a question that turns on case law, consider calling canlex_case on the \
201
  leading decision's neutral citation to confirm it has not been overtaken.
 
 
 
 
 
 
 
202
  - You may call tools multiple times; iterate until you have enough material to \
203
  answer well. Aim for thoroughness but stop once further calls would not change \
204
  the answer.
@@ -361,6 +466,15 @@ def _summarize_call(name: str, args: dict) -> str:
361
  return f"Looking up case {args.get('case_url', '?')}"
362
  if name == "canlex_list_acts":
363
  return "Listing the CanLex corpus"
 
 
 
 
 
 
 
 
 
364
  return f"Calling {name}"
365
 
366
 
 
175
  "required": ["case_url"],
176
  },
177
  },
178
+ {
179
+ "name": "canlex_us_disposition",
180
+ "description": (
181
+ "Assess whether a US criminal disposition (deferred adjudication, "
182
+ "withheld adjudication, nolo plea, expungement, state pardon, "
183
+ "diversion, juvenile adjudication...) is a 'conviction' for IRPA "
184
+ "s. 36 inadmissibility, with a 51-jurisdiction state-by-state "
185
+ "breakdown. Use for ANY question involving a US criminal record. "
186
+ "Step 1 of the s. 36 screening flow."
187
+ ),
188
+ "parameters": {
189
+ "type": "object",
190
+ "properties": {
191
+ "disposition": {
192
+ "type": "string",
193
+ "description": (
194
+ "The disposition in the record's own words, e.g. "
195
+ "'deferred adjudication', 'withheld adjudication', "
196
+ "'expunged conviction' -- or 'all' for the full table."
197
+ ),
198
+ },
199
+ "state": {
200
+ "type": "string",
201
+ "description": "Optional US state name or 2-letter code.",
202
+ },
203
+ },
204
+ "required": ["disposition"],
205
+ },
206
+ },
207
+ {
208
+ "name": "canlex_us_equivalency",
209
+ "description": (
210
+ "Map a common US offence (DUI, theft, assault, fraud, drug "
211
+ "possession, disorderly conduct...) to its Canadian equivalent "
212
+ "offence, verified maximum penalty, and the IRPA s. 36 branch "
213
+ "(serious criminality vs criminality vs none). Step 2 of the "
214
+ "s. 36 screening flow; its max-penalty answer feeds step 3."
215
+ ),
216
+ "parameters": {
217
+ "type": "object",
218
+ "properties": {
219
+ "offense": {
220
+ "type": "string",
221
+ "description": "The US offence as charged, e.g. 'DUI'.",
222
+ },
223
+ },
224
+ "required": ["offense"],
225
+ },
226
+ },
227
+ {
228
+ "name": "canlex_rehabilitation",
229
+ "description": (
230
+ "Assess deemed rehabilitation / eligibility to apply for "
231
+ "individual rehabilitation under IRPA s. 36(3)(c) and IRPR "
232
+ "ss. 17-18.1, from offence severity, count and time elapsed. "
233
+ "Step 3 of the s. 36 screening flow."
234
+ ),
235
+ "parameters": {
236
+ "type": "object",
237
+ "properties": {
238
+ "basis": {
239
+ "type": "string",
240
+ "description": (
241
+ "'foreign-conviction', 'foreign-act', or "
242
+ "'canada-conviction'."
243
+ ),
244
+ },
245
+ "max_penalty_lt_10": {
246
+ "type": "boolean",
247
+ "description": (
248
+ "True if the equivalent Canadian offence's maximum is "
249
+ "under 10 years (see canlex_us_equivalency)."
250
+ ),
251
+ },
252
+ "count": {
253
+ "type": "string",
254
+ "description": (
255
+ "'one', 'two-plus-summary-only', or 'multiple'."
256
+ ),
257
+ },
258
+ "years_elapsed": {
259
+ "type": "integer",
260
+ "description": (
261
+ "Full years since the day after the entire sentence "
262
+ "was completed (or since commission, for acts)."
263
+ ),
264
+ },
265
+ "clean_record": {
266
+ "type": "boolean",
267
+ "description": "True if no other convictions or acts.",
268
+ },
269
+ },
270
+ "required": ["basis", "max_penalty_lt_10", "count",
271
+ "years_elapsed", "clean_record"],
272
+ },
273
+ },
274
  ]
275
 
276
+ # Tools whose MCP signature wraps arguments under a single 'params' object.
277
+ # canlex_list_acts takes none and is handled separately in _run_tool.
278
+ _PARAMS_WRAPPED = {"canlex_search_legislation", "canlex_get_section",
279
+ "canlex_case", "canlex_us_disposition",
280
+ "canlex_us_equivalency", "canlex_rehabilitation"}
281
 
282
 
283
  # --- System prompt ------------------------------------------------------------
 
285
  SYSTEM_INSTRUCTION = """\
286
  You are CanLex Web, a Canadian legal-research assistant. A member of the public \
287
  has asked the legal question shown below through a web form. Answer it by \
288
+ agentically using the CanLex tools to retrieve primary sources, then \
289
  compose a clear, well-organised answer grounded entirely in what those tools \
290
  return.
291
 
 
297
  canlex_search_legislation again to fetch it. Do not guess its contents.
298
  - For a question that turns on case law, consider calling canlex_case on the \
299
  leading decision's neutral citation to confirm it has not been overtaken.
300
+ - US CRIMINAL RECORDS -- the three-step screening flow: (1) \
301
+ canlex_us_disposition: is the disposition a conviction at all (state-aware)? \
302
+ (2) canlex_us_equivalency: what Canadian offence does it equate to, and is it \
303
+ serious criminality or criminality? (3) canlex_rehabilitation: has time cured \
304
+ it (deemed rehabilitation / eligibility to apply)? Chain all three when the \
305
+ question involves a US record and enough facts are given; ask for the missing \
306
+ facts (state, disposition wording, dates) when they are not.
307
  - You may call tools multiple times; iterate until you have enough material to \
308
  answer well. Aim for thoroughness but stop once further calls would not change \
309
  the answer.
 
466
  return f"Looking up case {args.get('case_url', '?')}"
467
  if name == "canlex_list_acts":
468
  return "Listing the CanLex corpus"
469
+ if name == "canlex_us_disposition":
470
+ state = f" ({args['state']})" if args.get("state") else ""
471
+ return (f"Checking US disposition "
472
+ f"`{args.get('disposition', '?')}`{state}")
473
+ if name == "canlex_us_equivalency":
474
+ return f"Mapping US offence `{args.get('offense', '?')}` to Canadian law"
475
+ if name == "canlex_rehabilitation":
476
+ return (f"Assessing rehabilitation "
477
+ f"({args.get('years_elapsed', '?')} years elapsed)")
478
  return f"Calling {name}"
479
 
480