{"schema_version":"1.0","service":{"name":"AgentBroker","id":"agent-broker","version":"0.2.16","description":"A horizontal, agent-callable broker that lets an autonomous agent discover, verify, communicate with, schedule with, and transact with the long tail of small and mid-size businesses through one clean tool surface. Routes internally through whatever channel actually reaches the SMB: direct API, voice AI, SMS, email, web form, or browser automation.","base_url":"https://api.hatchloop.dev","discovery_url":"https://api.hatchloop.dev/.well-known/mcp.json","contact":"hello@hatchloop.dev"},"operations":[{"name":"find_business","description":"Find real businesses near a place, sorted by distance (nearest of those examined; see result.search). Data: OpenStreetMap (ODbL, (c) OSM contributors); phone, website, hours only when mapped. Coverage varies; community-mapped, NOT verified by us; source=openstreetmap rows cannot be booked. Answers within about 5 s: status partial (search_in_progress) means repeat the call. If OSM is down: retriable 'temporarily unavailable', never invented rows.","readiness":{"state":"beta","summary":"Community-mapped OpenStreetMap data, unverified. A place the public servers are slow for answers partial/search_in_progress at 5 s; repeat the same call and it is usually served from cache."},"when_to_use":"Use when an agent needs real businesses of a given kind near a place: to show options, get contact details, or pick a target. Rows with source=supply_network (added through booking URLs) can then be booked with schedule_appointment; rows with source=openstreetmap are for contact details, not booking.","when_not_to_use":"Do not use as a bulk directory or scraping surface: results are capped at 20, fresh lookups are rate limited per caller, and the public OpenStreetMap servers behind this are a shared free service. Do not use when you already have a specific SMB identifier. Do not assume an OpenStreetMap result is verified, open right now, or bookable.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["location"],"properties":{"vertical":{"type":"string","enum":["personal_services","home_services","professional_services"]},"location":{"type":"object","required":["zip_or_city"],"properties":{"zip_or_city":{"type":"string","description":"Town, city, address or postal code, with the country if not US: 'Nizwa, Oman'. A bare 5-digit ZIP is a US ZIP; add the country for any other postal code."},"radius_miles":{"type":"number","minimum":0,"description":"Radius in miles (default 3.1, max 25); applies to OpenStreetMap results only."}},"description":"City/town or ZIP, optionally with country ('Nizwa, Oman'). Geocoded by OSM."},"capability":{"type":"string","description":"Kind of business: 'dentist', 'cafe', 'plumber'. Use it or vertical."},"price_band":{"type":"object","properties":{"max_usd":{"type":"number"}},"description":"Supply-network rows only (OpenStreetMap has no prices)."},"availability_window":{"type":"object","properties":{"start_iso":{"type":"string","format":"date-time"},"end_iso":{"type":"string","format":"date-time"}},"description":"Accepted but NOT APPLIED: it does not narrow results (no live calendars). The result says availability_window_applied: false. To book a slot use schedule_appointment requested_time."},"max_results":{"type":"integer","default":5,"maximum":20,"minimum":1},"city":{"type":"string","description":"Instead of location: a city, e.g. 'Muscat, Oman'."},"region":{"type":"string","description":"With city: a state or region."}}},"output_schema":{"type":"object","properties":{"businesses":{"type":"array","items":{"type":"object","properties":{"smb_id":{"type":"string"},"name":{"type":"string"},"vertical":{"type":"string"},"address":{"type":"string"},"capabilities":{"type":"array","items":{"type":"string"}},"channels_available":{"type":"array","items":{"type":"string"}},"price_range":{"type":"object"},"verified_at":{"type":"string","format":"date-time"},"rank_score":{"type":"number"},"source":{"type":"string","enum":["openstreetmap","supply_network"]},"category":{"type":"string","description":"OpenStreetMap tag that matched, e.g. shop=hairdresser (OSM rows only)"},"address_parts":{"type":"object","description":"housenumber, street, suburb, city, state, postcode, country - only those the map holds"},"phone":{"type":"string"},"website":{"type":"string"},"opening_hours":{"type":"string","description":"OpenStreetMap opening_hours syntax, as mapped"},"latitude":{"type":"number"},"longitude":{"type":"number"},"distance_m":{"type":"integer","description":"Metres from the geocoded search point"},"osm":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"integer"},"url":{"type":"string"}}}}}},"result_count":{"type":"integer","description":"How many rows are in businesses. 0 with search.status ok means a search that ran to the end and found none; 0 with status pending means it has not finished."},"total_in_supply_network":{"type":"integer","description":"Real (non-sample) supply-network rows overall"},"attribution":{"type":"string","description":"Always present. (c) OpenStreetMap contributors - required by the ODbL"},"attribution_url":{"type":"string"},"license":{"type":"string"},"input_notes":{"type":"array","items":{"type":"string"},"description":"Present when the request was read more loosely than the schema says: a string location, a kind of business sent as vertical, a top-level city, a clamped max_results"},"ignored_arguments":{"type":"array","items":{"type":"string"},"description":"Argument names that were sent and not used"},"location_normalized_from":{"type":"object","description":"The top-level city / region / country that were assembled into location.zip_or_city"},"search":{"type":"object","description":"What was actually searched: status (ok, pending, location_not_found, unavailable, rate_limited), geocoded_place, radius_m (the radius really used; smaller than radius_requested_m when a dense area was narrowed), category_match {basis, osm_tags}, candidates_considered, candidates_capped, distance_order, cached, budget_s, within_budget","properties":{"provider":{"type":"string"},"status":{"type":"string","enum":["ok","pending","location_not_found","unavailable","rate_limited","not_requested"],"description":"pending = the time budget ran out before the search came back; it is still running and an identical repeat is usually answered from cache. Not an outage and not 'no businesses'."},"reason":{"type":"string"},"retry_after_s":{"type":"integer"},"budget_s":{"type":"number","description":"The time budget for this call, in seconds"},"within_budget":{"type":"boolean","description":"False when status is pending"},"continues_in_background":{"type":"boolean","description":"Present (true) when status is pending"},"repeat_this_call":{"type":"string"},"radius_m":{"type":"integer","description":"Radius actually searched, in metres"},"radius_requested_m":{"type":"integer"},"radius_narrowed":{"type":"boolean","description":"True when the requested area held more than 150 matches and a smaller circle was searched so the nearest ones are not missed"},"candidates_capped":{"type":"boolean","description":"True when more matches exist than the 150 candidates examined; rows are then the nearest among those examined, not guaranteed nearest overall"},"distance_order":{"type":"string","enum":["exact","nearest_of_examined"],"description":"exact = every match within radius_m was examined"},"country_restriction":{"type":"string","description":"Present (us) when a bare 5-digit ZIP was read as a US ZIP"},"narrowing_stopped_because":{"type":"string"}}},"osm_notice":{"type":"string"},"supply_coverage_note":{"type":"string"}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":5000,"p95_ms":5500,"success_rate_30d":null,"availability_30d":null,"supply_network_coverage_by_vertical":null},"idempotency":"read-only — idempotency key not required","failure_modes":["bad_input","missing_capability","rate_limited","search_in_progress","osm_temporarily_unavailable","out_of_supply_network","transient","internal"],"examples":[{"label":"Happy path - find hair salons near Atlanta (illustrative output)","input":{"vertical":"personal_services","location":{"zip_or_city":"Atlanta, GA"},"capability":"haircut","max_results":3},"output":{"status":"success","businesses":[{"smb_id":"osm:node/1001","name":"Example Cuts","source":"openstreetmap","category":"shop=hairdresser","address":"12 Peachtree St, Atlanta, GA 30303","address_parts":{"housenumber":"12","street":"Peachtree St","city":"Atlanta","state":"GA","postcode":"30303"},"phone":"+1 404 555 0100","opening_hours":"Mo-Sa 09:00-18:00","latitude":33.7495,"longitude":-84.3885,"distance_m":60,"osm":{"type":"node","id":1001,"url":"https://www.openstreetmap.org/node/1001"}}],"attribution":"(c) OpenStreetMap contributors","search":{"provider":"openstreetmap","status":"ok","radius_m":5000}}},{"label":"No results - say so, do not read it as 'none exist'","input":{"vertical":"professional_services","location":{"zip_or_city":"99999"},"capability":"tax_consultation"},"output":{"status":"success","businesses":[],"attribution":"(c) OpenStreetMap contributors","search":{"provider":"openstreetmap","status":"location_not_found"},"supply_coverage_note":"OpenStreetMap could not resolve the location to a place. Try a city or town name, optionally with the country."}},{"label":"OpenStreetMap unreachable - retriable, no invented rows","input":{"vertical":"home_services","location":{"zip_or_city":"Muscat, Oman"},"capability":"plumber"},"output":{"status":"failure","reason_code":"osm_temporarily_unavailable","retriable":true,"businesses":[],"attribution":"(c) OpenStreetMap contributors","search":{"provider":"openstreetmap","status":"unavailable","reason":"upstream_timeout","retry_after_s":30}}}],"user_query_examples":[{"user_says":"Find me a salon in Tokyo that does color","agent_call":{"tool":"find_business","arguments":{"vertical":"personal_services","location":{"zip_or_city":"Tokyo"},"capability":"color"}}},{"user_says":"I need a plumber near 30309","agent_call":{"tool":"find_business","arguments":{"vertical":"home_services","location":{"zip_or_city":"30309"},"capability":"plumbing"}}},{"user_says":"Show me dentists in London","agent_call":{"tool":"find_business","arguments":{"vertical":"professional_services","location":{"zip_or_city":"London"},"capability":"dentist"}}}]},{"name":"verify_business","description":"Look up what we know about a business in our supply network: contact channels, capabilities, last verification. A DIRECTORY LOOKUP - it does not contact the business. Supply-network ids only, not osm:... ids.","readiness":{"state":"limited","summary":"Directory lookup of supply-network records only (ids from import_booking_url). An unknown id, or an osm:... id returned by find_business, answers out_of_supply_network (not retriable). It never contacts the business."},"when_to_use":"Use before sending communications or scheduling if you have an unverified SMB identifier, or if the agent's task requires confirmed capability (e.g., 'I need to be sure they do emergency plumbing').","when_not_to_use":"Do not use if the SMB was returned from find_business within the last 24 hours — those results are already verified.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["smb_id"],"properties":{"smb_id":{"type":"string"},"capability_to_verify":{"type":"string"}}},"output_schema":{"type":"object","properties":{"verified":{"type":"boolean"},"capabilities_confirmed":{"type":"array","items":{"type":"string"}},"channels_reachable":{"type":"array","items":{"type":"string"}},"last_verified_at":{"type":"string","format":"date-time"},"verification_method":{"type":"string"}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":500,"p95_ms":2000},"idempotency":"read-only — idempotency key not required","failure_modes":["bad_input","out_of_supply_network","supply_unverified","transient"],"examples":[{"label":"Verified with direct API","input":{"smb_id":"smb_001","capability_to_verify":"haircut"},"output":{"status":"success","result":{"verified":true,"capabilities_confirmed":["haircut","blowdry"],"channels_reachable":["direct_api:square"],"verification_method":"directory_lookup"}}}],"user_query_examples":[{"user_says":"Confirm smb_imp_abc actually does emergency plumbing","agent_call":{"tool":"verify_business","arguments":{"smb_id":"smb_imp_abc","capability_to_verify":"emergency_plumbing"}}}]},{"name":"send_message","description":"Send a message on behalf of an agent's user or an SMB across WhatsApp (free during launch), SMS, email, or voice, sent immediately, no scheduling. Every send passes a non-bypassable gate: TCPA, GDPR, CASL where modeled, else the service's own opt-in default (the Gulf included). Marketing on SMS, voice, WhatsApp and non-US email without recorded opt-in is rejected (compliance_violation receipt). US marketing email follows CAN-SPAM opt-out rules.","when_to_use":"Use to: (a) confirm a booking the agent just made, (b) reply to a customer who messaged the SMB first, (c) follow up on a quote the user requested, (d) send appointment reminders the SMB owes its customer, (e) send marketing messages to recipients who have opted in. Where opt-in is required (everything except US marketing email, which follows CAN-SPAM opt-out rules) the gate verifies it on every send.","when_not_to_use":"Do NOT use for OTPs or critical transactional confirmations — use send_transactional_confirmation. Do NOT attempt to send SMS, voice, WhatsApp or non-US email marketing without a recorded opt-in — the gate will reject the send and log a compliance_violation (US marketing email follows CAN-SPAM opt-out rules instead). Do NOT attempt bulk / list-based / drip / cold outreach — those are out of scope and the rate limiter will throttle abuse.","execution_profile":"sync_fast","compliance_constraints":["Permitted message types: transactional, marketing, reminder, follow_up, notification.","Marketing on SMS, voice, WhatsApp and non-US email requires a recorded opt-in at send time — the gate looks it up in the consent_store and rejects if missing, expired, or revoked. US marketing email follows CAN-SPAM opt-out rules: no prior opt-in is required, and a recorded opt-out is honored.","US SMS marketing requires TCPA prior express written consent + 10DLC campaign registration.","EU/UK recipients require explicit GDPR lawful basis (contract or freely-given consent) for marketing messages.","Canadian recipients require CASL express consent for commercial electronic messages.","Voice channel to US recipients requires prior express consent for autodialed/prerecorded calls (TCPA).","All commercial email contains a functional unsubscribe link (CAN-SPAM).","Gulf recipients (UAE, SA, OM, QA, KW, BH): no Gulf statute is modeled, so the gate applies the service's own opt-in default (recorded opt-in for marketing, an 08:00-21:00 local solicitation window) and its answer says so. The country is read from the recipient's number; a marketing or follow-up message whose country_code contradicts the number is refused as jurisdiction_conflict."],"input_schema":{"type":"object","required":["recipient","message_type","content"],"properties":{"recipient":{"type":"object","required":["id_type","id_value"],"properties":{"id_type":{"type":"string","enum":["phone","email","smb_id","customer_id"]},"id_value":{"type":"string"},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2, required for compliance routing"}}},"message_type":{"type":"string","description":"'marketing' needs recorded opt-in, except US email (CAN-SPAM opt-out rules). Five types. The gate checks the opt-in at send time and rejects the send (compliance_violation receipt) if it is missing, expired, or revoked.","enum":["transactional","marketing","reminder","follow_up","notification"]},"content":{"type":"object","required":["body"],"properties":{"body":{"type":"string"},"subject":{"type":"string","description":"For email channel"},"template_id":{"type":"string"},"template_vars":{"type":"object"}}},"preferred_channel":{"type":"string","enum":["whatsapp","sms","email","voice","auto"],"default":"auto"},"on_behalf_of":{"type":"string","description":"Who this message is FOR (your end-user's name/label). On WhatsApp this opens a tracked conversation and travels in-message as '#4821 for Sara (via HatchLoop)', so the business knows who it is talking to and their reply is matched back to this exact request instead of guessed. Strongly recommended for two-way channels."},"business_id":{"type":"string","description":"Stable id for the recipient business; used for global demand shaping."}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call_variable","unit_price_usd":0.02,"credits":2,"max_price_usd":0.22,"max_credits":22,"notes":"Reserves up to 22 credits and settles the actual cost from the receipt; minimum 2."},"slo":{"p50_ms":800,"p95_ms":4000},"idempotency":"required — use Idempotency-Key header to prevent duplicate sends","failure_modes":["bad_input","compliance_violation","consent_missing","supply_unreachable","upstream_failure","rate_limited","budget_exceeded"],"examples":[{"label":"SMS appointment reminder — happy path","input":{"recipient":{"id_type":"phone","id_value":"+14045550100","country_code":"US"},"message_type":"reminder","content":{"body":"Reminder: your appointment at Cuts & Co. is tomorrow at 10am. Reply STOP to unsubscribe."},"preferred_channel":"sms"},"output":{"status":"success","channel_used":"sms:twilio","cost":{"amount":0.05,"currency":"USD"}}},{"label":"Consumer asked agent to follow up on a quote","input":{"recipient":{"id_type":"smb_id","id_value":"smb_044","country_code":"US"},"message_type":"follow_up","content":{"body":"Hi — checking back on the plumbing quote I requested yesterday for Maple St. Could you share availability for Thursday?"}},"output":{"status":"success","channel_used":"sms:twilio","cost":{"amount":0.02,"currency":"USD"}}},{"label":"Marketing SMS blocked — no recorded consent","input":{"recipient":{"id_type":"phone","id_value":"+14045550200","country_code":"US"},"message_type":"marketing","content":{"body":"20% off this week only!"}},"output":{"status":"failure","reason_code":"compliance_violation","human_message":"Recipient +14045550200 has not opted in to marketing SMS. TCPA prior express written consent is required. Obtain consent (consent_record_id) and retry.","retriable":false}},{"label":"Marketing SMS to an opted-in subscriber (consent passes the gate)","input":{"recipient":{"id_type":"phone","id_value":"+14045550100","country_code":"US"},"message_type":"marketing","content":{"body":"Cuts & Co.: Fall sale this Saturday — 20% off cuts + color. Reply STOP to opt out."}},"output":{"status":"success","channel_used":"sms:twilio","cost":{"amount":0.02,"currency":"USD"}}},{"label":"Voice fallback when SMS unreachable","input":{"recipient":{"id_type":"phone","id_value":"+12125550300","country_code":"US"},"message_type":"reminder","content":{"body":"Your appointment is tomorrow at 2pm."}},"output":{"status":"success","channel_used":"voice_ai:vapi","channel_fallback_chain":["sms:twilio (carrier_filter)","voice_ai:vapi (success)"],"cost":{"amount":0.3,"currency":"USD"}}}],"user_query_examples":[{"user_says":"Text the salon I'll be 10 minutes late","agent_call":{"tool":"send_message","arguments":{"recipient":{"id_type":"smb_id","id_value":"smb_xyz"},"message_type":"notification","content":{"body":"Running about 10 minutes late for my appointment."},"preferred_channel":"sms"}}},{"user_says":"Email the dentist about insurance","agent_call":{"tool":"send_message","arguments":{"recipient":{"id_type":"email","id_value":"front-desk@example-dental.com"},"message_type":"transactional","content":{"body":"Do you accept Cigna insurance?"},"preferred_channel":"email"}}}]},{"name":"capture_lead","description":"Structured intake of a prospect into an SMB's funnel with validation and deduplication on (smb_id, phone or email). Stored in AgentBroker's own lead funnel, NOT the business's CRM; the business is not notified.","readiness":{"state":"beta","summary":"Writes to AgentBroker's own lead funnel and stops there: this tool does not notify the business or update its CRM. Needs a supply-network smb_id (from import_booking_url); an unknown id or an osm:... id is refused with out_of_supply_network."},"when_to_use":"Use when a potential customer has expressed interest in an SMB's service and you want to ensure they are registered in the SMB's pipeline for follow-up.","when_not_to_use":"Do not use for confirmed bookings — use schedule_appointment. Do not use for bulk list imports.","execution_profile":"sync_fast","compliance_constraints":["Captured lead data is subject to GDPR data subject rights for EU residents.","CAN-SPAM applies if captured email will receive commercial messages.","Retention policy is enforced per jurisdiction by ComplianceAgent."],"input_schema":{"type":"object","required":["smb_id","prospect"],"properties":{"smb_id":{"type":"string"},"prospect":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"service_interest":{"type":"string"},"notes":{"type":"string"},"consent_record_id":{"type":"string","description":"Optional ID of a consent record proving the prospect asked to be contacted (e.g., they filled an SMB's intake form or requested a quote). Required when downstream send_message calls are anticipated."}}},"source":{"type":"string","description":"Where the consumer-initiated request originated (e.g., 'consumer_request', 'inbound_quote_form', 'agent_referral_from_find_business')."}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call","unit_price_usd":0.05,"credits":5},"slo":{"p50_ms":600,"p95_ms":3000},"idempotency":"required — dedupe is keyed on (smb_id, prospect.phone or prospect.email)","failure_modes":["bad_input","out_of_supply_network","idempotency_conflict","upstream_failure","compliance_violation"],"examples":[{"label":"Happy path — lead captured into Square CRM","input":{"smb_id":"smb_001","prospect":{"name":"Jane Smith","phone":"+14045551234","email":"jane@example.com","service_interest":"haircut"},"source":"agent_referral"},"output":{"status":"success","result":{"lead_id":"lead_abc123","channel_used":"direct_api:square"}}}],"user_query_examples":[{"user_says":"Tell smb_xyz I'm interested and want a callback","agent_call":{"tool":"capture_lead","arguments":{"smb_id":"smb_xyz","prospect":{"name":"Jane","phone":"+15551234567","email":"jane@example.com"},"source":"agent"}}}]},{"name":"schedule_appointment","description":"Check availability, book, or cancel via Cal.com. Only completes when the SMB's imported booking link is bound to this deployment's ONE connected Cal.com account; otherwise fails honestly (booking_destination_unmapped) with no charge. No working booking path exists yet for non-Cal.com platforms (voice AI, web form) — those SMBs fail honestly instead of a fabricated confirmation.","readiness":{"state":"limited","summary":"Completes only for a business whose booking link is bound to this deployment's one connected Cal.com account. Any other business fails with booking_destination_unmapped, uncharged."},"when_to_use":"Use to book, check availability, or cancel a Cal.com appointment once the SMB is verified and its booking link is bound to our connected Cal.com account. Requires a verified smb_id.","when_not_to_use":"Do not use for bulk scheduling. Do not use without a verified SMB — call find_business and verify_business first if needed. Do not pass action=reschedule — it is not implemented; cancel the existing appointment and book a new time instead. Do not expect this to book on the SMB's own Calendly/Doctolib/Booksy/Fresha/etc. account, or on a Cal.com account other than the one this deployment holds credentials for — those calls fail honestly with no charge.","execution_profile":"async_by_default","compliance_constraints":["Voice channel to US recipients requires prior express consent for prerecorded calls (TCPA).","Voice recording in CA, FL, IL, MD, MA, MT, NV, NH, PA, WA requires two-party consent — recording-consent prompt fires automatically."],"input_schema":{"type":"object","required":["smb_id","action"],"properties":{"smb_id":{"type":"string"},"action":{"type":"string","enum":["book","cancel","check_availability"]},"service":{"type":"string"},"customer":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"}}},"requested_time":{"type":"object","properties":{"preferred_iso":{"type":"string","format":"date-time"},"window_start_iso":{"type":"string","format":"date-time"},"window_end_iso":{"type":"string","format":"date-time"},"duration_minutes":{"type":"integer"}}},"existing_appointment_id":{"type":"string","description":"Required for cancel"},"notes":{"type":"string"}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call_variable","unit_price_usd":0.15,"credits":15,"max_price_usd":0.5,"max_credits":50,"notes":"Reserves up to 50 credits and settles the actual cost from the receipt; minimum 15."},"slo":{"p50_ms":5000,"p95_ms":60000,"note":"async — p50/p95 reflect time to terminal outcome, not HTTP response"},"idempotency":"required — prevents double-booking on network retry","failure_modes":["bad_input","action_not_supported","out_of_supply_network","supply_unreachable","upstream_failure","compliance_violation","recording_consent_missing","outcome_rejected","booking_destination_unmapped","async_channel_not_provisioned"],"examples":[{"label":"Book haircut — direct API path","input":{"smb_id":"smb_001","action":"book","service":"haircut","customer":{"name":"Alex Johnson","phone":"+14045559999"},"requested_time":{"window_start_iso":"2026-04-29T09:00:00Z","window_end_iso":"2026-04-29T12:00:00Z"}},"output":{"status":"pending_async","operation_id":"op_xyz789","estimated_completion_time":"2026-04-27T10:01:00Z","next_actions":["poll get_status with operation_id op_xyz789","or await webhook callback"]}},{"label":"Book plumber with no Cal.com link — honest failure (no working non-Cal.com path yet)","input":{"smb_id":"smb_044","action":"book","service":"emergency_plumbing","requested_time":{"preferred_iso":"2026-04-28T08:00:00Z"}},"output":{"status":"failure","reason_code":"async_channel_not_provisioned","human_message":"smb_044 can only be booked through an async channel, which needs a background worker that is not deployed on this tier. Nothing was booked and nothing was charged.","cost":{"amount":0.0,"currency":"USD","basis":"no_charge"}}},{"label":"Cancel appointment","input":{"smb_id":"smb_001","action":"cancel","existing_appointment_id":"appt_cal_4455"},"output":{"status":"success","reason_code":"cancelled","result":{"refund_status":"pending","confirmation_number":"CANCEL-789"}}}],"user_query_examples":[{"user_says":"Book the haircut for next Tuesday at 3pm","agent_call":{"tool":"schedule_appointment","arguments":{"smb_id":"smb_imp_abc","action":"book","service":"haircut"}}},{"user_says":"Cancel my Friday appointment at smb_xyz","agent_call":{"tool":"schedule_appointment","arguments":{"smb_id":"smb_xyz","action":"cancel"}}},{"user_says":"What times does the dentist have open next week?","agent_call":{"tool":"schedule_appointment","arguments":{"smb_id":"smb_imp_xyz","action":"check_availability"}}}]},{"name":"send_transactional_confirmation","description":"Idempotent transactional messages: OTPs, booking confirmations, payment receipts, cancellation notices. Falls back across configured channels; an unconfigured channel fails honestly rather than reporting a delivery that did not happen.","when_to_use":"Use for any message that MUST be delivered reliably — OTPs, booking confirmations, receipts. Do not use for marketing.","when_not_to_use":"Do not use for marketing or promotional messages. Do not use for conversational messages.","execution_profile":"sync_fast","compliance_constraints":["Transactional messages are exempt from marketing consent rules but must include clear identification of sender and purpose."],"input_schema":{"type":"object","required":["recipient","confirmation_type","data"],"properties":{"recipient":{"type":"object","required":["phone_or_email"],"properties":{"phone_or_email":{"type":"string"},"name":{"type":"string"}}},"confirmation_type":{"type":"string","enum":["otp","booking_confirmation","payment_receipt","cancellation_notice","reminder"]},"data":{"type":"object","description":"Type-specific payload; e.g., {otp_code} for otp, {appointment_time, smb_name} for booking_confirmation"},"preferred_channel":{"type":"string","enum":["sms","email","auto"],"default":"sms"}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call","unit_price_usd":0.02,"credits":2},"slo":{"p50_ms":500,"p95_ms":2000},"idempotency":"required — Idempotency-Key prevents double-sends of OTPs and confirmations","failure_modes":["bad_input","upstream_failure","supply_unreachable"],"examples":[{"label":"Booking confirmation SMS","input":{"recipient":{"phone_or_email":"+14045551234","name":"Alex"},"confirmation_type":"booking_confirmation","data":{"appointment_time":"Tuesday April 29 at 10:30am","smb_name":"Cuts & Co.","address":"123 Main St, Atlanta"}},"output":{"status":"success","channel_used":"sms:twilio"}}],"user_query_examples":[{"user_says":"Send the booking confirmation receipt to my email","agent_call":{"tool":"send_transactional_confirmation","arguments":{"recipient":{"id_type":"email","id_value":"customer@example.com"},"confirmation_type":"booking_confirmation","data":{"appointment_time":"2026-09-03T15:00:00Z","business_name":"Salon 718"},"preferred_channel":"email"}}}]},{"name":"handle_inbound","description":"Classify an inbound message for an SMB and get a suggested_action for YOUR agent to act on. English keyword rules (booking request, cancellation, opt-out, inquiry, complaint): treat the intent as a hint. Opt-outs are recorded durably; nothing else is auto-routed or executed.","readiness":{"state":"beta","summary":"Substring keyword rules on English text, not a language model: 'stop' or 'cancel' anywhere in a message sets the intent. A hint for your agent to check, never a decision."},"when_to_use":"Use when an SMB needs inbound message triage — classifying incoming contact-form submissions, SMS replies, voicemails, or email inquiries.","when_not_to_use":"Do not use for outbound communications. Do not use for compliance-flagged recipient lists without verified opt-in records.","execution_profile":"async_by_default","compliance_constraints":["Inbound message content may contain PII — retained per jurisdiction retention policy.","GDPR data subject deletion requests received via inbound must be escalated immediately."],"input_schema":{"type":"object","required":["smb_id","inbound_channel","raw_message"],"properties":{"smb_id":{"type":"string"},"inbound_channel":{"type":"string","enum":["sms","email","voice_voicemail","web_form","api"]},"sender":{"type":"object","properties":{"phone":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"}}},"raw_message":{"type":"string"},"received_at_iso":{"type":"string","format":"date-time"},"routing_rules":{"type":"object","description":"Optional override routing policy for this SMB"}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call","unit_price_usd":0.03,"credits":3},"slo":{"p50_ms":3000,"p95_ms":15000},"idempotency":"required","failure_modes":["bad_input","upstream_failure","transient"],"examples":[{"label":"Inbound SMS booking request triaged","input":{"smb_id":"smb_001","inbound_channel":"sms","sender":{"phone":"+14045551234"},"raw_message":"Hi, do you have anything Saturday morning?","received_at_iso":"2026-04-27T14:00:00Z"},"output":{"status":"success","result":{"classified_intent":"booking_inquiry","suggested_action":"check_availability","routed_to":"schedule_appointment_flow","enriched_sender":{"known_customer":true,"last_booking":"2026-03-15"}}}}],"user_query_examples":[{"user_says":"Process this customer reply for me: 'Yes I want to book Tuesday'","agent_call":{"tool":"handle_inbound","arguments":{"smb_id":"smb_xyz","inbound_channel":"sms","raw_message":"Yes I want to book Tuesday"}}}]},{"name":"escalate_to_human","description":"Hand off an in-flight task to a human operator with a context bundle (transcript, prior actions, identifiers, recommended next step). Writes a ticket to the operator queue; sends no notification, promises no response time.","readiness":{"state":"beta","summary":"Writes a ticket to the operator queue and returns its id. This tool sends no notification and makes no response-time commitment."},"when_to_use":"Use when automated resolution has failed after channel-fallback exhaustion, when the task requires human judgment, or when the customer has explicitly requested human contact.","when_not_to_use":"Do not use as a first resort. Escalate only after automated resolution attempts.","execution_profile":"async_by_default","compliance_constraints":["Context bundle may contain PII — handled per jurisdiction retention policy.","Recording transcripts included in handoff must have recording consent confirmed."],"input_schema":{"type":"object","required":["smb_id","reason","context"],"properties":{"smb_id":{"type":"string"},"reason":{"type":"string","enum":["automation_failed","customer_requested","compliance_hold","ambiguous_intent","exception_required"]},"context":{"type":"object","properties":{"original_operation":{"type":"string"},"operation_id":{"type":"string"},"transcript":{"type":"array","items":{"type":"object"}},"prior_actions":{"type":"array","items":{"type":"object"}},"recommended_next_step":{"type":"string"}}},"priority":{"type":"string","enum":["normal","urgent"],"default":"normal"}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call","unit_price_usd":0.2,"credits":20},"slo":{"p50_ms":2000,"p95_ms":10000},"idempotency":"required","failure_modes":["bad_input","supply_unreachable","upstream_failure"],"examples":[{"label":"Escalation after voice AI booking failure","input":{"smb_id":"smb_044","reason":"automation_failed","context":{"original_operation":"schedule_appointment","operation_id":"op_fail_001","recommended_next_step":"Call the business directly at their listed number to confirm the emergency plumbing slot"}},"output":{"status":"success","result":{"escalation_ticket_id":"esc_777","assigned_queue":"smb_support"}}}],"user_query_examples":[{"user_says":"I'm stuck — get a human at smb_xyz to call me back","agent_call":{"tool":"escalate_to_human","arguments":{"smb_id":"smb_xyz","reason":"automation_failed","context":{"original_operation":"schedule_appointment","recommended_next_step":"Call the business directly to confirm the slot"},"priority":"urgent"}}}]},{"name":"get_status","description":"Query the current state of any in-flight async operation by operation_id.","when_to_use":"Use to poll the state of a pending_async operation when no webhook callback has arrived or to check progress.","when_not_to_use":"Do not poll more frequently than once per 10 seconds — use webhook delivery for real-time updates instead.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["operation_id"],"properties":{"operation_id":{"type":"string"}}},"output_schema":{"type":"object","properties":{"operation_id":{"type":"string"},"status":{"type":"string","enum":["pending","executing","success","failure","partial","not_found","forbidden"]},"estimated_completion_time":{"type":"string","format":"date-time"},"last_updated_at":{"type":"string","format":"date-time"},"partial_result":{"type":"object"}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":50,"p95_ms":200},"idempotency":"read-only","failure_modes":["bad_input","transient","not_your_operation","identity_required"],"examples":[{"label":"Booking still in progress","input":{"operation_id":"op_xyz789"},"output":{"status":"executing","estimated_completion_time":"2026-04-27T10:01:30Z"}}]},{"name":"get_outcome","description":"Retrieve the final OutcomeReceipt for a completed operation.","when_to_use":"Use after get_status returns success/failure/partial to retrieve the full result with cost and reason codes.","when_not_to_use":"Do not use for operations still in pending/executing state — use get_status first.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["operation_id"],"properties":{"operation_id":{"type":"string"}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":50,"p95_ms":200},"idempotency":"read-only","failure_modes":["bad_input","transient","not_your_operation","identity_required"],"examples":[{"label":"Retrieve booking outcome","input":{"operation_id":"op_xyz789"},"output":{"status":"success","reason_code":"appointment_confirmed","result":{"appointment_id":"appt_cal_9001","confirmed_time":"2026-04-29T10:30:00Z","smb_name":"Cuts & Co."},"cost":{"amount":1.0,"currency":"USD","basis":"per_booking_attempt+success_bonus"},"channel_used":"direct_api:square"}}]},{"name":"preview_cost","description":"Return an expected cost estimate, latency estimate, and success-probability estimate for a proposed call before execution. Returns the exact price when it is fixed, and a min/max range when the cost depends on channel or outcome. It does not promise an accuracy percentage - check cost_range.","when_to_use":"Use before any operation when the agent is operating under a budget constraint and needs to decide whether to proceed.","when_not_to_use":"Do not use in a hot loop — cache the result for at least 60 seconds if repeating the same preview.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["operation","params"],"properties":{"operation":{"type":"string"},"params":{"type":"object","description":"The same request body you would pass to the operation"}}},"output_schema":{"type":"object","properties":{"estimated_cost_usd":{"type":"number"},"cost_range":{"type":"object","properties":{"min_usd":{"type":"number"},"max_usd":{"type":"number"}}},"estimated_latency_p50_ms":{"type":"integer"},"estimated_latency_p95_ms":{"type":"integer"},"success_probability_estimate":{"type":"number","minimum":0,"maximum":1},"channel_likely":{"type":"string"},"cost_accuracy_slo":{"type":"string","description":"Basis of the estimate, not a tolerance. 'exact' when the price is fixed and the preview IS the charge; otherwise a range - consult cost_range for min/max. No accuracy percentage is promised: nothing measures preview against the eventual charge.","examples":["exact","range: see cost_range (min/max)"]}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":100,"p95_ms":500},"idempotency":"read-only","failure_modes":["bad_input","transient"],"examples":[{"label":"Preview appointment booking cost","input":{"operation":"schedule_appointment","params":{"smb_id":"smb_001","action":"book","service":"haircut"}},"output":{"estimated_cost_usd":1.0,"cost_range":{"min_usd":0.25,"max_usd":1.0},"estimated_latency_p50_ms":5000,"success_probability_estimate":0.88,"channel_likely":"direct_api:square","cost_accuracy_slo":"±5%"}}],"user_query_examples":[{"user_says":"How much will this SMS cost me?","agent_call":{"tool":"preview_cost","arguments":{"operation":"send_message","params":{"preferred_channel":"sms"}}}},{"user_says":"Estimate the cost of booking via voice fallback","agent_call":{"tool":"preview_cost","arguments":{"operation":"schedule_appointment","params":{"preferred_channel":"voice"}}}}]},{"name":"self_test","description":"Service health probe: runs 6 internal checks and reports how many passed. Confirms the server is up and responding - it does NOT probe each tool individually. Use to verify connectivity before production use.","when_to_use":"Use at agent startup, before high-stakes task sequences, or after receiving unexpected errors to check if the service is degraded.","when_not_to_use":"Do not call more than once per minute in production.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","properties":{}},"output_schema":{"type":"object","properties":{"healthy":{"type":"boolean","description":"True when every internal check passed. This is the field to branch on."},"all_passed":{"type":"boolean","description":"Alias of healthy."},"passed":{"type":"integer","description":"Checks that passed."},"failed":{"type":"integer","description":"Checks that failed."},"total":{"type":"integer","description":"Number of checks run. Derived from the check list, not a fixed number."},"latency_ms":{"type":"number","description":"How long the checks took."},"failed_checks":{"type":"array","items":{"type":"string"},"description":"Names of the checks that failed. Absent when none did."},"version":{"type":"string","description":"Manifest version."}},"required":["healthy","all_passed","passed","failed","total"]},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":200,"p95_ms":1000},"idempotency":"read-only","failure_modes":["transient","internal"],"examples":[{"label":"Healthy service response","input":{},"output":{"healthy":true,"all_passed":true,"passed":6,"failed":0,"total":6,"latency_ms":10.45}}],"user_query_examples":[{"user_says":"Run a health check before I send the broadcast","agent_call":{"tool":"self_test","arguments":{}}}]},{"name":"check_quota","description":"Returns the caller's current quota state: how many operations have been used today, how many remain, the daily limit, the tier (free / credits / unlimited), and when the quota resets. Read-only and free. Works with any valid X-Agent-Identity token; returns tier='anonymous' for keyless callers with the anonymous daily limits.","when_to_use":"Call at session start or before a batch of write operations to confirm you have enough remaining quota. Use when a user asks how many API calls they have left today. Also useful after a rate_limited error to understand when the quota resets.","when_not_to_use":"Do not call on every single tool invocation — quota is also injected into every write-tool response in the 'quota' field. Only call proactively when you need the current state without performing an operation.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":[],"properties":{}},"output_schema":{"type":"object","properties":{"tier":{"type":"string","enum":["free","credits","unlimited","anonymous"],"description":"Caller tier. 'free' = email-verified free key (100 ops/day). 'credits' = paid credit account. 'unlimited' = subscription plan (developer/business/enterprise). 'anonymous' = no key."},"daily_limit":{"type":["integer","null"],"description":"Daily operation limit for gated write tools. null for unlimited tiers."},"used_today":{"type":"integer","description":"Number of gated write-tool ops consumed today (UTC day)."},"remaining_today":{"type":["integer","null"],"description":"Ops remaining today before rate_limited. null for unlimited tiers."},"resets":{"type":"string","format":"date-time","description":"ISO-8601 UTC timestamp of next daily quota reset (midnight UTC)."},"key_id":{"type":["string","null"],"description":"Parsed agent_id from the bearer token, or null for anonymous callers."},"data_quota":{"type":"object","description":"Quota state for the 3 premium data tools (verify_company_record, screen_sanctions, map_trade_restriction). Only present when DATA_METERING_ENABLED=true.","properties":{"daily_limit":{"type":"integer"},"remaining_today":{"type":"integer"},"resets":{"type":"string","format":"date-time"}}}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":5,"p95_ms":20},"idempotency":"read-only — idempotency key not required","failure_modes":[],"examples":[{"label":"Free-tier caller checks remaining ops","input":{},"output":{"tier":"free","daily_limit":100,"used_today":12,"remaining_today":88,"resets":"2026-09-02T00:00:00Z","key_id":"free_4f19be4f"}},{"label":"Anonymous caller","input":{},"output":{"tier":"anonymous","daily_limit":null,"used_today":0,"remaining_today":null,"resets":"2026-09-02T00:00:00Z","key_id":null}}],"user_query_examples":[{"user_says":"How many API calls do I have left today?","agent_call":{"tool":"check_quota","arguments":{}}},{"user_says":"Check my quota before sending messages","agent_call":{"tool":"check_quota","arguments":{}}},{"user_says":"When does my rate limit reset?","agent_call":{"tool":"check_quota","arguments":{}}}]},{"name":"check_booking_link","description":"Free, instant pre-flight check for a booking URL. Classifies which booking platform a URL belongs to and tells you whether import_booking_url will accept it, WITHOUT fetching the page or spending money. Returns the platform, the exact smb_id import_booking_url would assign, the channels the booking will route through, and the inferred country. Use it to de-risk a paid booking BEFORE calling import_booking_url + schedule_appointment.","when_to_use":"Call this the moment a user pastes a URL and you are not sure it is a bookable page, or before you commit to a paid schedule_appointment. It is free and sub-100ms, so run it as a guard: if supported=true, proceed to import_booking_url with confidence; if supported=false, fall back to find_business or call_business instead of wasting a booking attempt.","when_not_to_use":"Do not use to confirm the page is currently live/available — this tool does not fetch the URL, it only classifies its shape. It is not a substitute for import_booking_url (which actually registers the business) or verify_business (which confirms an already-imported smb_id).","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"Full http(s) URL to classify, e.g. 'https://cal.com/jane' or 'https://www.opentable.com/r/acme'."}}},"output_schema":{"type":"object","properties":{"supported":{"type":"boolean","description":"True if the URL host is a supported booking platform."},"importable":{"type":"boolean","description":"True if import_booking_url will accept this URL (mirrors its host allowlist)."},"platform":{"type":"string","description":"Detected platform (e.g. 'cal.com', 'calendly', 'doctolib') or 'unknown'."},"predicted_smb_id":{"type":"string","description":"The idempotent smb_id import_booking_url would assign to this URL."},"expected_channels":{"type":"array","items":{"type":"string"}},"expected_capabilities":{"type":"array","items":{"type":"string"}},"inferred_country":{"type":"string"},"checked_live":{"type":"boolean","description":"Always false — this is an offline classification, the page is never fetched."}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":20,"p95_ms":100},"idempotency":"read-only","failure_modes":["bad_input"],"examples":[{"label":"Supported Cal.com link","input":{"url":"https://cal.com/jane"},"output":{"supported":true,"importable":true,"platform":"cal.com","predicted_smb_id":"smb_imp_...","expected_channels":["direct_api:calcom"],"checked_live":false}},{"label":"Unsupported generic URL","input":{"url":"https://example.com/book-now"},"output":{"supported":false,"importable":false,"platform":"unknown"}}],"user_query_examples":[{"user_says":"Is this a bookable link? https://cal.com/jane","agent_call":{"tool":"check_booking_link","arguments":{"url":"https://cal.com/jane"}},"then_call":{"tool":"import_booking_url","arguments":{"booking_url":"https://cal.com/jane"}}},{"user_says":"Can you book me here: https://www.opentable.com/r/acme-bistro","agent_call":{"tool":"check_booking_link","arguments":{"url":"https://www.opentable.com/r/acme-bistro"}}}]},{"name":"import_booking_url","description":"Turn a public booking URL into a callable smb_id for send_message and capture_lead. But schedule_appointment only completes on Cal.com bound to our one connected account — the other 11 always fail schedule_appointment honestly, uncharged. Detects 12 platforms (Cal.com, Calendly, Doctolib, Booksy, Fresha, OpenTable, Setmore, Square, Acuity, Schedulista, Squarespace, BookMyCity). Idempotent — calling twice returns the same smb_id.","readiness":{"state":"limited","summary":"Detects 12 booking platforms, but only a Cal.com link bound to our one connected account can be booked afterwards; the other 11 fail schedule_appointment honestly, uncharged. Needs a key."},"when_to_use":"Call this FIRST whenever the user provides a specific booking URL (cal.com/handle, calendly.com/handle/event, doctolib.fr/..., booksy.com/..., opentable.com/r/..., etc.). User patterns that match: 'book me at https://cal.com/...', 'schedule with calendly.com/jane/intro', 'reserve a table at opentable.com/r/...', 'I want to book this dentist: https://www.doctolib.fr/...'. After importing, the returned smb_id works immediately with send_message and capture_lead. It only completes a booking via schedule_appointment if the URL was a Cal.com link bound to this deployment's one connected account — every other platform gets an honest, uncharged refusal there, not a booking.","when_not_to_use":"Do not use if the user only describes a business by name without a URL — call find_business instead. Do not use for arbitrary websites that are not on the supported booking-platform list (use /supply/platforms to see all 12).","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["booking_url"],"properties":{"booking_url":{"type":"string","format":"uri","description":"Full URL the user supplied. Must point at one of the 12 supported booking platforms; auto-detected from the host."},"business_name":{"type":"string","description":"If omitted, auto-extracted from the page's <title> or og:title."},"vertical":{"type":"string","enum":["personal_services","home_services","professional_services","restaurants","retail","healthcare","fitness"],"description":"If omitted, inferred from the booking platform."},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 (e.g. 'US', 'FR'); routes compliance on later sends."},"contact_phone":{"type":"string","description":"If omitted, the platform integration handles outreach."},"contact_email":{"type":"string"},"capabilities":{"type":"array","items":{"type":"string"},"description":"Free-form capability tags (e.g., ['haircut','color','blowdry'])."}}},"output_schema":{"type":"object","required":["status","smb_id"],"properties":{"status":{"type":"string","enum":["success","duplicate","fail"]},"smb_id":{"type":"string","description":"Stable identifier — works with send_message and capture_lead immediately. schedule_appointment only books with it if this was a Cal.com URL bound to our one connected account."},"platform":{"type":"string","description":"Detected platform name."},"message":{"type":"string"},"next_steps":{"type":"array","items":{"type":"string"}}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_latency_ms":600,"max_latency_ms":3000},"examples":[{"user_says":"Book me a haircut at https://cal.com/jane-salon","agent_call":{"tool":"import_booking_url","arguments":{"booking_url":"https://cal.com/jane-salon","vertical":"personal_services"}},"then_call":{"tool":"schedule_appointment","arguments":{"smb_id":"<from_above>","preferred_time":"user-specified"}}},{"user_says":"I want to see Dr. Dupont — https://www.doctolib.fr/dentiste/paris/jean-dupont","agent_call":{"tool":"import_booking_url","arguments":{"booking_url":"https://www.doctolib.fr/dentiste/paris/jean-dupont"}}}],"user_query_examples":[{"user_says":"Book me a haircut at https://cal.com/jane-salon","agent_call":{"tool":"import_booking_url","arguments":{"booking_url":"https://cal.com/jane-salon","vertical":"personal_services"}},"then_call":{"tool":"schedule_appointment","arguments":{"smb_id":"<from_above>","action":"book"}}},{"user_says":"Schedule with this dentist: https://www.doctolib.fr/dentiste/paris/jean-dupont","agent_call":{"tool":"import_booking_url","arguments":{"booking_url":"https://www.doctolib.fr/dentiste/paris/jean-dupont"}}},{"user_says":"Reserve a table at https://www.opentable.com/r/acme-bistro","agent_call":{"tool":"import_booking_url","arguments":{"booking_url":"https://www.opentable.com/r/acme-bistro","vertical":"restaurants"}}}],"idempotency":{"key_scope":["agent_id","booking_url"],"ttl_seconds":86400,"behavior":"Calling import_booking_url twice with the same URL returns the same smb_id (no duplicate). Safe to retry."},"failure_modes":[{"reason_code":"platform_not_supported","retriable":false,"description":"Host did not match any of the 12 supported booking platforms."},{"reason_code":"url_not_reachable","retriable":true,"description":"The page returned 404 / 403 / timeout. Retry after fixing the URL."},{"reason_code":"page_metadata_extraction_failed","retriable":false,"description":"Page exists but we could not extract a usable business name. Pass `business_name` explicitly."}]},{"name":"call_business","description":"Place a conversational voice-AI phone call to a business on a consumer's behalf; give a plain-language objective and it navigates the call, extracting the answer. Business-directed (B2B), far less restricted than calling consumers — but the compliance gate still enforces recording consent per jurisdiction.","when_to_use":"Use when the target business has NO booking URL and NO API — only a phone number — and the consumer asked the agent to reach them (e.g. 'call this plumber and ask if they can come Tuesday', 'ask the salon if they take walk-ins this afternoon'). Also use to confirm details a booking page doesn't expose (real-time availability, custom quotes).","when_not_to_use":"Do NOT use when the business has a booking URL — use import_booking_url + schedule_appointment (cheaper, faster, deterministic). Do NOT use for calls to consumers/individuals (this tool is for reaching businesses). Do NOT use for marketing or telemarketing — the compliance gate and the B2B-only framing reject that.","execution_profile":"async_by_default","compliance_constraints":["Business-directed voice call. The opening line identifies the caller as an AI assistant acting on a consumer's behalf.","Recording consent enforced per jurisdiction (two-party-consent states/countries get a spoken consent prompt before recording).","Not for consumer-directed autodialing or prerecorded marketing (TCPA) — objective must be an operational business question."],"input_schema":{"type":"object","required":["objective"],"properties":{"business_phone":{"type":"string","description":"Business phone in E.164 (e.g. +14045550123). Provide this OR smb_id."},"smb_id":{"type":"string","description":"Known SMB identifier with a phone on record. Provide this OR business_phone."},"objective":{"type":"string","description":"What the call should accomplish, in plain language."},"extract_fields":{"type":"array","items":{"type":"string"},"description":"Structured fields to pull from the answer, e.g. ['available_tomorrow','price_quote','earliest_slot']."},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 for compliance + recording-consent routing."},"on_behalf_of":{"type":"string","description":"Name of the consumer the call is placed for."},"max_duration_seconds":{"type":"integer","maximum":600,"default":180}}},"output_schema":{"$ref":"#/components/OutcomeReceipt"},"cost_model":{"basis":"per_call","unit_price_usd":0.2,"credits":20},"slo":{"p50_ms":45000,"p95_ms":180000},"idempotency":"NOT idempotent — each call places a new phone call. Do not retry a call_business that returned pending_async; poll get_outcome instead.","failure_modes":["bad_input","voice_not_provisioned","compliance_violation","upstream_failure"],"examples":[{"label":"Call a plumber with no booking page","input":{"business_phone":"+14045550142","objective":"Ask if they can do an emergency drain unclog tomorrow morning and roughly what it costs.","extract_fields":["available_tomorrow_am","price_estimate"],"country_code":"US","on_behalf_of":"the customer at 14 Maple St"},"output":{"status":"pending_async","reason_code":"call_placed","channel_used":"voice_ai:vapi","cost":{"amount":0.5,"currency":"USD"}}}]},{"name":"check_compliance","description":"Free, instant pre-flight for the compliance gate: runs the SAME TCPA/GDPR/CASL/CAN-SPAM/10DLC checks as send_message and call_business, in preview mode -- nothing is sent, nothing changes. Tells you whether a send would be permitted before you pay, and if not, names the exact rule and how to fix it. De-risks a paid send the way check_booking_link de-risks a paid booking.","when_to_use":"Call this the moment before send_message or call_business when there is any chance the send is regulated — anything tagged marketing, any SMS to a US number (10DLC), any message to an EU/UK (GDPR) or Canadian (CASL) recipient, or any content you are unsure about. It is free and sub-100ms, so run it as a guard: if legal=true, proceed to send_message with confidence; if legal=false, fix the cited blocker instead of burning a paid, rejected send.","when_not_to_use":"Do not treat a legal=true as a permanent license — the gate re-runs at send time, so a fresh opt-out between preview and send still blocks. Do not use it to check two-party voice recording consent (that is evaluated at call time in the voice adapter, not here). It is not a substitute for send_message; it never delivers anything.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["recipient_id","content"],"properties":{"recipient_id":{"type":"string","description":"Phone in E.164 (e.g. '+14045550100') or email address the message would go to."},"content":{"type":"string","description":"The actual message body you intend to send. The gate classifies the real text, so a meaningful preview needs the real content."},"channel":{"type":"string","enum":["sms","email","voice"],"description":"Delivery channel. Omit to auto-infer sms/email from recipient_id; set 'voice' explicitly."},"message_type":{"type":"string","description":"One of transactional, marketing, reminder, follow_up, notification (any case). Any other value is refused. 'marketing' triggers the consent checks. Defaults to transactional.","default":"transactional"},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 (e.g. 'US', 'DE', 'CA'). Auto-inferred from phone if omitted; drives which jurisdiction rules apply."},"state_code":{"type":"string","description":"US state code (e.g. 'CA') for state-specific rules."}}},"output_schema":{"type":"object","properties":{"legal":{"type":"boolean","description":"True if the gate would permit this send."},"channel":{"type":"string"},"message_type":{"type":"string"},"jurisdiction":{"type":"string"},"jurisdiction_source":{"type":"string","enum":["caller","recipient_number","unknown"],"description":"How the jurisdiction was decided: the caller's country_code, the recipient number's country calling code (which wins over a contradicting country_code for a message that is not a solicitation), or unknown (which includes a marketing or follow-up message whose country_code contradicts the number)."},"jurisdiction_conflict":{"type":"string","description":"Present only when country_code contradicted the recipient number or could not be used. For a message that is not a solicitation it says which jurisdiction was applied instead; for a marketing or follow-up message none was, and the answer is rule jurisdiction_conflict."},"rule_set":{"type":"object","description":"What the rules applied are based on. basis is 'statute' where a named statute is modeled (US, EU/UK states modeled, Canada) and 'conservative_default' everywhere else, which means no statute of that country was applied - the service's own opt-in policy was. It is 'undecided' (code null) when a marketing or follow-up message's country_code contradicts the recipient number: the gate refused to choose and applied no rule set.","properties":{"code":{"type":["string","null"]},"basis":{"type":"string","enum":["statute","conservative_default","undecided"]},"statutes_modeled":{"type":"array","items":{"type":"string"}},"note":{"type":"string"}}},"rule":{"type":"string","description":"The rule that blocked the send (null when legal=true)."},"remediation":{"type":"string","description":"How to become compliant (present when legal=false)."},"checked_live":{"type":"boolean","description":"Always false — this is a gate decision preview, not a live delivery."}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":15,"p95_ms":80},"idempotency":"read-only — no send, no audit write, no idempotency key required","failure_modes":["bad_input"],"examples":[{"label":"Transactional email is permitted","input":{"recipient_id":"jane@example.com","content":"Your appointment at Cuts & Co. is confirmed for Tuesday 10:30am.","message_type":"transactional","country_code":"US"},"output":{"status":"success","reason_code":"compliant","result":{"legal":true,"channel":"email","message_type":"transactional","checked_live":false}}},{"label":"Marketing SMS blocked — no recorded consent","input":{"recipient_id":"+14045550200","content":"20% off this week only!","channel":"sms","message_type":"marketing","country_code":"US"},"output":{"status":"success","reason_code":"not_compliant","result":{"legal":false,"rule":"TCPA_marketing_consent","remediation":"Obtain prior express written consent (TCPA) before sending marketing SMS to US numbers, and pass its consent_record_id.","checked_live":false}}}],"user_query_examples":[{"user_says":"Is it legal to text this US number a 20%-off promo?","agent_call":{"tool":"check_compliance","arguments":{"recipient_id":"+14045550200","content":"20% off this week only!","channel":"sms","message_type":"marketing","country_code":"US"}}},{"user_says":"Before you email the dentist, make sure it's allowed","agent_call":{"tool":"check_compliance","arguments":{"recipient_id":"office@dentist.example","content":"Do you accept Cigna? Following up on my request.","message_type":"follow_up"}},"then_call":{"tool":"send_message","arguments":{"recipient":{"id_type":"email","id_value":"office@dentist.example"},"message_type":"follow_up","content":{"body":"Do you accept Cigna? Following up on my request."}}}}]},{"name":"verify_company_record","description":"Free, live lookup of a company official registry record. Queries the GLEIF global LEI registry (primary, 2.6 million legal entities worldwide) and SEC EDGAR (US public companies) to return the official legal name, LEI, entity status, jurisdiction, registered address, and registry authority. Never fabricates: if the company is not found in these free registries, returns an honest not_found with the sources that were queried.","when_to_use":"Use when you need to verify that a company exists as a registered legal entity and retrieve its official registry details -- before signing a contract, qualifying a vendor, validating a counterparty, or populating a due-diligence record. Accepts a legal name plus optional country filter or a direct LEI for a precise lookup.","when_not_to_use":"Do not use to verify private companies not registered with GLEIF or SEC. Do not use as an exhaustive fraud-detection tool; this is a first-pass existence check against free public registries, not a full KYC screen.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Legal company name to look up, e.g. Apple Inc or Volkswagen AG."},"country":{"type":"string","description":"Optional ISO 3166-1 alpha-2 country filter (e.g. US, DE, GB). Narrows GLEIF results to one jurisdiction."},"lei":{"type":"string","description":"Optional 20-character Legal Entity Identifier for a direct, precise lookup."}}},"output_schema":{"type":"object","properties":{"status":{"type":"string","enum":["found","not_found"]},"legal_name":{"type":"string"},"lei":{"type":"string"},"entity_status":{"type":"string"},"jurisdiction":{"type":"string"},"registered_address":{"type":"string"},"registry_authority":{"type":"string"},"ticker":{"type":"string"},"sec_cik":{"type":"string"},"sources":{"type":"array","items":{"type":"string"}},"sources_queried":{"type":"array","items":{"type":"string"}},"sources_unavailable":{"type":"array","items":{"type":"string"}}}},"cost_model":{"basis":"freemium_daily_quota","unit_price_usd":0.02,"free_quota_note":"The daily free quota (500/day with a free email-verified key, 100/day anonymous) exists only while DATA_METERING_ENABLED is on; payments.premium_data_quota_enforced in /.well-known/mcp.json says whether it is. Beyond it a call is billed via credits only while a payment rail is on."},"slo":{"p50_ms":800,"p95_ms":4000},"idempotency":"read-only","failure_modes":["bad_input","upstream_timeout"],"examples":[{"label":"Look up Apple Inc by name and country","input":{"name":"Apple Inc","country":"US"},"output":{"status":"found","legal_name":"Apple Inc.","lei":"HWUPKR0MPOU8FGXBT394","entity_status":"ACTIVE","jurisdiction":"US","sources":["GLEIF","SEC EDGAR"]}},{"label":"Direct LEI lookup","input":{"name":"Volkswagen AG","lei":"529900HNOAA1KXQJUQ27"},"output":{"status":"found","legal_name":"Volkswagen AG","lei":"529900HNOAA1KXQJUQ27","entity_status":"ACTIVE","jurisdiction":"DE","sources":["GLEIF"]}},{"label":"Company not found in registries","input":{"name":"zzz-nonexistent-company-xyz"},"output":{"status":"not_found"}}],"user_query_examples":[{"user_says":"Is Apple Inc a real registered company?","agent_call":{"tool":"verify_company_record","arguments":{"name":"Apple Inc","country":"US"}}},{"user_says":"Look up the LEI for Volkswagen AG","agent_call":{"tool":"verify_company_record","arguments":{"name":"Volkswagen AG","country":"DE"}}},{"user_says":"Verify this LEI: 529900HNOAA1KXQJUQ27","agent_call":{"tool":"verify_company_record","arguments":{"name":"Volkswagen AG","lei":"529900HNOAA1KXQJUQ27"}}}]},{"name":"screen_sanctions","description":"Free screening of a name/entity (Latin or Arabic script) against sanctions lists: OFAC SDN (US Treasury), EU consolidated list (European Commission), UK Sanctions List (FCDO). THE UN CONSOLIDATED LIST IS NOT SCREENED -- no licence permits redistribution. Never fabricates a match or clear: check lists_screened; reason_code 'partial_screening' (never 'clear') if any source failed.","when_to_use":"Use before onboarding a counterparty, processing a payment, engaging a vendor, or doing any due-diligence step that requires knowing whether a person or entity appears on official sanctions lists. Essential for agents doing business formation, vendor qualification, payments onboarding, trade compliance, or any workflow where a sanctioned counterparty is a legal or reputational risk.","when_not_to_use":"Do not use as a substitute for full KYC/AML screening -- this covers sanctions lists only, not PEP (Politically Exposed Person) databases, adverse media, or credit risk. Do not treat a negative result as a compliance clearance; it is informational only. Do not use for bulk screening of large lists -- each call is a live API query. Arabic names are matched by transliteration, which is lossy: sound-alikes come back as graded candidates (match_confidence, token_alignment), never as findings; the one exception is an Arabic-script name equal to an Arabic alias a list prints. An Arabic query with no hits is 'partial', never 'clean'.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name of the person or entity to screen, in Latin or Arabic script, e.g. 'Kim Jong-un' or 'ACME Trading LLC'. Use the most complete name available. Arabic names are also matched by sound across spellings."},"country":{"type":"string","description":"Optional ISO 3166-1 alpha-2 country code or country name (e.g. 'IR', 'Iran'). It ANNOTATES AND RANKS results; it never removes any. Each EU/UK match carries country_match: true, false, or null when the listing records no country. Nothing is dropped on a mismatch, because the country we hold is the address/nationality on the listing rather than everywhere a party operates - excluding on it would return a clean screen for someone who IS listed."},"type":{"type":"string","enum":["person","entity"],"description":"Optional entity type hint. 'person' for individuals, 'entity' for organizations/companies. Omit to screen both."}}},"output_schema":{"type":"object","properties":{"matched":{"type":"boolean","description":"True only when a CONFIRMED match was found. False does NOT by itself mean clean - it is also false when no list could be screened. Branch on screening_status and review_guidance for independent coverage/review tasks, not on this."},"review_guidance":{"type":"object","description":"Additive deterministic review hints, bound by compliance_receipt. Coverage means supported OFAC/EU/UK paths only; hit/candidates may coexist with missing coverage. Does not assert identity, KYC/AML clearance or permission to transact. Action identifiers describe review tasks and confer no authorization.","properties":{"version":{"type":"string","const":"agentbroker-screening-review/1"},"coverage_scope":{"type":"string","const":"supported_lists_only"},"coverage_status":{"type":"string","enum":["complete","partial","none"]},"lists_screened":{"type":"array","items":{"type":"string"}},"lists_not_screened":{"type":"array","items":{"type":"string"}},"lists_outside_scope":{"type":"array","items":{"type":"string"}},"review_required":{"type":"boolean","description":"True when name/candidate, coverage, freshness or matching limitations require review. False is not clearance."},"review_reasons":{"type":"array","items":{"type":"string","enum":["confirmed_name_match","unverified_candidates","incomplete_coverage","unknown_list_freshness","stale_list_copy","name_not_fully_screenable","lossy_transliteration"]}},"next_actions":{"type":"array","items":{"type":"string","enum":["verify_identity_against_official_source","review_candidates_against_official_source","retry_unavailable_lists","verify_list_freshness","provide_screenable_name","review_original_script_and_aliases"]}},"freshness_unknown_lists":{"type":"array","items":{"type":"string"}},"stale_copy_lists":{"type":"array","items":{"type":"string"}},"does_not_assert":{"type":"string"}}},"screening_status":{"type":"string","enum":["hit","clean","partial","candidates","not_screened"],"description":"What actually happened, because matched:false was ambiguous between two opposite answers. 'hit' = confirmed match. 'clean' = EVERY list screened and nothing found. 'partial' = some lists screened and clean, others did not run - not a full clearance. 'candidates' = screened, nothing confirmed, but possible_matches_unverified is non-empty and a human should look. 'not_screened' = NO list produced a complete screen (outage, stale or unknown-age index, or a name too short/generic to match on safely) - this is not a result and must never be treated as clean. Check lists_screened and sources_unavailable for which was which."},"matches":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Name as it appears on the sanctions list"},"list":{"type":"string","description":"Sanctions list name (e.g. OFAC-SDN, EU-Financial-Sanctions)"},"match_score":{"type":"number","description":"Match confidence 0.0-1.0 (higher = more confident)"},"program":{"type":"string","description":"Sanctions program (e.g. SDGT, IRAN, RUSSIA-EO14024)"},"entity_type":{"type":"string","description":"INDIVIDUAL, ENTITY, VESSEL, or AIRCRAFT"},"source_url":{"type":"string","description":"URL of the authoritative source record"}}}},"lists_screened":{"type":"array","items":{"type":"string"},"description":"Human-readable list of which sanctions lists were actually queried."},"sources_queried":{"type":"array","items":{"type":"string"},"description":"API/data URLs that were called during screening."},"screened_at":{"type":"string","format":"date-time","description":"UTC timestamp when the screening was performed."},"disclaimer":{"type":"string","description":"Informational disclaimer -- results are not legal advice."},"sources_unavailable":{"type":"array","items":{"type":"string"},"description":"Sources that were attempted but unavailable (fail-open: partial results returned)."},"arabic_matching":{"type":"object","description":"Present when the name was Arabic-script or showed Arabic-name structure. Says whether the sound-based layer ran (applied, not_applied_reason), what it searched on (query_elements), how many candidates it produced (sound_based_candidates) and how many low-confidence pairs it counted but did not list (low_confidence_not_listed). Each sound-based candidate in possible_matches_unverified also carries match_basis, match_confidence (high or medium), match_explanation and token_alignment."}}},"cost_model":{"basis":"freemium_daily_quota","unit_price_usd":0.02,"free_quota_note":"The daily free quota (500/day with a free email-verified key, 100/day anonymous) exists only while DATA_METERING_ENABLED is on; payments.premium_data_quota_enforced in /.well-known/mcp.json says whether it is. Beyond it a call is billed via credits only while a payment rail is on."},"slo":{"p50_ms":2000,"p95_ms":8000,"max_latency_ms":12000,"notes":"Latency dominated by list downloads behind a 6-hour cache: OFAC SDN is a ~5MB CSV from Treasury; the EU and UK lists are served from our own indexed copy, refreshed daily."},"idempotency":"full","failure_modes":[{"code":"bad_input","description":"name field is empty or missing","retriable":false},{"code":"partial_screening","description":"One or more upstream sources was unavailable; matches from remaining sources returned","retriable":true},{"code":"sources_all_unavailable","description":"All upstreams timed out or errored; no screening could be performed","retriable":true}],"examples":[{"label":"Screen a known sanctioned individual","input":{"name":"Kim Jong-un","country":"KP","type":"person"},"output":{"matched":true,"matches":[{"name":"KIM, Jong Un","list":"OFAC-SDN","match_score":1.0,"program":"DPRK","entity_type":"INDIVIDUAL","source_url":"https://ofac.treasury.gov/sanctions-list-service"}],"screened_at":"2026-08-23T00:00:00Z","disclaimer":"Informational screening only, not legal advice; confirm against the official source before acting on any result."}},{"label":"Screen a clean (non-sanctioned) name","input":{"name":"Jane Smith"},"output":{"matched":false,"matches":[],"screened_at":"2026-08-23T00:00:00Z","disclaimer":"Informational screening only, not legal advice; confirm against the official source before acting on any result."}},{"label":"Partial result when one upstream is down","input":{"name":"ACME Trading LLC"},"output":{"matched":false,"matches":[],"sources_unavailable":["UK-SANCTIONS (local index unreachable; NOT screened on this call)"],"screened_at":"2026-08-23T00:00:00Z","disclaimer":"Informational screening only, not legal advice; confirm against the official source before acting on any result."}}],"user_query_examples":[{"user_says":"Screen this vendor before we pay them: ACME Trading LLC, Russia","agent_call":{"tool":"screen_sanctions","arguments":{"name":"ACME Trading LLC","country":"RU","type":"entity"}}},{"user_says":"Is Kim Jong-un on the OFAC list?","agent_call":{"tool":"screen_sanctions","arguments":{"name":"Kim Jong-un","country":"KP","type":"person"}}},{"user_says":"Run a sanctions check on this person before onboarding","agent_call":{"tool":"screen_sanctions","arguments":{"name":"Ivan Petrov","country":"RU","type":"person"}}},{"user_says":"Do a compliance check -- is this company sanctioned?","agent_call":{"tool":"screen_sanctions","arguments":{"name":"Mahan Air","country":"IR","type":"entity"}}}]},{"name":"map_trade_restriction","description":"Free cross-border screening of destination and parties: DOES NOT CLASSIFY THE PRODUCT: echoed back, never checked against export-control lists, so a controlled item to an unrestricted destination returns 'partial', never 'clear'. Not an export-control clearance -- classify HS/ECCN yourself. Never fabricates a tariff rate, a clear, or a restricted status.","when_to_use":"Use before any cross-border trade to flag embargoed destinations, screen exporters/importers/freight forwarders against sanctions lists, and get authoritative links to the applicable tariff databases. Call this as a pre-flight check before quoting, invoicing, or shipping internationally. Covers OFAC comprehensively-embargoed countries (Iran, North Korea, Cuba, Syria) and significant advisory countries (Russia, Belarus, Ukraine Crimea/DNR/LNR regions).","when_not_to_use":"Do NOT use as a substitute for a licensed export compliance review. Do NOT use to obtain authoritative tariff rates (this tool returns guidance links, never fabricated rates). Do NOT use for purely domestic shipments where no cross-border movement is involved.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["product","destination_country"],"properties":{"product":{"type":"string","description":"Product name or description, e.g. 'laptop computers', 'crude oil', 'medical devices'. Used in the tariff guidance note."},"hs_code":{"type":"string","description":"Optional Harmonized System code (e.g. '8471.30' for laptops). If provided, echoed back and included in tariff guidance. Not derived -- caller must supply the official HS code."},"origin_country":{"type":"string","description":"Optional ISO 3166-1 alpha-2 code for the exporting country (e.g. 'US', 'DE'). Used in the tariff guidance note."},"destination_country":{"type":"string","description":"ISO 3166-1 alpha-2 code for the importing country (e.g. 'IR', 'CA', 'DE'). Required. Checked against the OFAC comprehensive-embargo map and sectoral-sanctions advisory list."},"parties":{"type":"array","maxItems":20,"items":{"type":"string"},"description":"Optional list of party names to screen (exporter, importer, freight forwarder, end-user, etc.). Each name is screened against OFAC SDN (US Treasury), the EU Consolidated list (European Commission) and the UK Sanctions List (FCDO). At most 20 parties per call - a longer list is refused outright (bad_input) rather than partially screened; split it across calls."}}},"output_schema":{"type":"object","properties":{"restricted":{"type":"boolean","description":"True if the destination has a comprehensive embargo OR any party matches an official sanctions list. False otherwise (advisory-only restrictions still appear in restrictions[])."},"restrictions":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"embargo | sanctions | export_control"},"list":{"type":"string","description":"Name of the applicable sanctions/control list"},"entity":{"type":"string","description":"The matched party name, or null for country-level restrictions"},"detail":{"type":"string","description":"Human-readable restriction detail"},"source_url":{"type":"string","description":"URL of the authoritative source record"}}}},"hs_code_hint":{"type":"string","description":"The HS code provided by the caller, echoed back. Null if not provided -- use official classification tools to obtain the correct HS code."},"destination_risk":{"type":"string","enum":["comprehensive_embargo","sectoral_sanctions","elevated_scrutiny","standard"],"description":"Risk level of the destination country based on OFAC and export-control programmes."},"tariff_note":{"type":"string","description":"Honest tariff guidance with links to USITC HTS, EU TARIC, Canada CBSA, and UK Trade Tariff. Rates are NOT provided to avoid misinformation."},"tariff_source":{"type":"string","description":"Always 'guidance' -- this tool never provides live tariff rates."},"parties_screened":{"type":"array","items":{"type":"object","properties":{"party":{"type":"string"},"matched":{"type":"boolean"},"matches":{"type":"array"},"sources_queried":{"type":"array","items":{"type":"string"}}}}},"sources_queried":{"type":"array","items":{"type":"string"},"description":"Data sources that were consulted during the check."},"screened_at":{"type":"string","format":"date-time","description":"UTC timestamp when the check was performed."},"disclaimer":{"type":"string","description":"Informational disclaimer -- results are not legal advice."}}},"cost_model":{"basis":"freemium_daily_quota","unit_price_usd":0.02,"free_quota_note":"The daily free quota (500/day with a free email-verified key, 100/day anonymous) exists only while DATA_METERING_ENABLED is on; payments.premium_data_quota_enforced in /.well-known/mcp.json says whether it is. Beyond it a call is billed via credits only while a payment rail is on."},"slo":{"p50_ms":3000,"p95_ms":10000,"max_latency_ms":15000,"notes":"Latency dominated by party screening upstream calls. With no parties, response is near-instant (hardcoded destination check only). Each additional party adds ~2-8s for concurrent sanctions screening."},"idempotency":"full","failure_modes":[{"code":"bad_input","description":"product is empty or destination_country is missing or not a valid ISO2 code","retriable":false},{"code":"restricted","description":"Destination is comprehensively embargoed or a party matched a sanctions list","retriable":false},{"code":"advisory","description":"Destination has sectoral sanctions or elevated scrutiny but no comprehensive embargo and no party matches","retriable":false},{"code":"partial_screening","description":"One or more upstream sources unavailable; partial results returned (fail-open)","retriable":true}],"examples":[{"label":"Embargoed destination -- Iran","input":{"product":"laptop computers","destination_country":"IR"},"output":{"restricted":true,"destination_risk":"comprehensive_embargo","restrictions":[{"type":"embargo","list":"OFAC-Comprehensive-Sanctions-Programme","entity":null,"detail":"Iran -- OFAC comprehensive sanctions programme...","source_url":"https://ofac.treasury.gov/countries"}],"tariff_source":"guidance","screened_at":"2026-08-24T00:00:00Z"}},{"label":"Clean lane -- US to Canada, common product","input":{"product":"office furniture","origin_country":"US","destination_country":"CA"},"output":{"restricted":false,"destination_risk":"standard","restrictions":[],"tariff_source":"guidance","screened_at":"2026-08-24T00:00:00Z"}},{"label":"Sanctioned party in the supply chain","input":{"product":"steel pipes","destination_country":"DE","parties":["Kim Jong-un"]},"output":{"restricted":true,"destination_risk":"standard","parties_screened":[{"party":"Kim Jong-un","matched":true,"matches":[{"list":"OFAC-SDN","match_score":0.95}]}],"tariff_source":"guidance","screened_at":"2026-08-24T00:00:00Z"}},{"label":"Russia advisory with HS code provided","input":{"product":"hydraulic pumps","hs_code":"8413.50","destination_country":"RU"},"output":{"restricted":false,"destination_risk":"sectoral_sanctions","hs_code_hint":"8413.50","tariff_source":"guidance","screened_at":"2026-08-24T00:00:00Z"}}],"user_query_examples":[{"user_says":"Can we ship laptops to Iran?","agent_call":{"tool":"map_trade_restriction","arguments":{"product":"laptop computers","destination_country":"IR"}}},{"user_says":"Screen this supplier before we import from them: Mahan Air, Iran","agent_call":{"tool":"map_trade_restriction","arguments":{"product":"aircraft parts","destination_country":"US","parties":["Mahan Air"]}}},{"user_says":"Is exporting hydraulic pumps to Russia restricted?","agent_call":{"tool":"map_trade_restriction","arguments":{"product":"hydraulic pumps","hs_code":"8413.50","destination_country":"RU"}}},{"user_says":"Check if we can sell medical devices to Germany, supplier is ACME GmbH","agent_call":{"tool":"map_trade_restriction","arguments":{"product":"medical devices","origin_country":"US","destination_country":"DE","parties":["ACME GmbH"]}}}]},{"name":"get_conversation","description":"Read a two-way conversation thread you started: its state, every message exchanged, and how many replies the business has sent.","when_to_use":"After send_message with on_behalf_of returns a conversation_id, poll this to read the business's reply. Replies are matched to the right thread exactly (never guessed), so what you read here belongs to YOUR end-user.","when_not_to_use":"Do not poll more often than every 10 seconds.","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","properties":{"conversation_id":{"type":"string","description":"From the send_message receipt (preferred)."},"reference":{"type":"string","description":"The 4-digit request reference, e.g. '4821'. Requires business_number."},"business_number":{"type":"string","description":"Scopes a `reference` to one business (references are reused across businesses)."}}},"output_schema":{"type":"object","properties":{"conversation_id":{"type":"string"},"reference":{"type":"string"},"state":{"type":"string","enum":["open","awaiting_reply","confirmed","closed"]},"awaiting_reply":{"type":"boolean"},"reply_count":{"type":"integer"},"messages":{"type":"array","items":{"type":"object"}}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"Free and unmetered. An agent identity IS required: a thread is readable only by the identity that opened it."},"slo":{"p50_ms":300,"p95_ms":1200},"idempotency":{"safe_to_retry":true,"key":"none - read-only"},"failure_modes":[{"reason_code":"conversation_not_found","retriable":false,"meaning":"No thread matched the id/reference given.","agent_action":"Use the conversation_id returned by send_message, or a reference plus business_number."},{"reason_code":"invalid_argument","retriable":false,"meaning":"A reference was supplied without business_number.","agent_action":"Add business_number - 4-digit references are reused across businesses."},{"reason_code":"not_your_conversation","retriable":false,"meaning":"The thread belongs to a different agent identity.","agent_action":"Use the identity that created the conversation."},{"reason_code":"identity_required","retriable":false,"meaning":"No agent identity was presented. A thread is readable only by the identity that opened it, so this tool needs one even though it is free.","agent_action":"Get a free key (email-verified, no payment) at /keys/request, then send it as the X-Agent-Identity header on this call. mint_key is not a route for outside callers: it needs the operator's machine-mint secret."},{"reason_code":"conversation_owner_unknown","retriable":false,"meaning":"The thread has no recorded owner, so it cannot be attributed to any caller and is released to none. Threads opened before caller identity was bound, and threads opened by a caller that sent no key, are in this state.","agent_action":"Send X-Agent-Identity with send_message and read back the thread that call returns."}],"examples":[{"user_says":"Did the salon reply about Sara's booking?","agent_call":{"tool":"get_conversation","arguments":{"conversation_id":"conv_1a2b3c4d"}},"returns":"state=awaiting_reply, reply_count=1, messages=[out: request, in: 'yes 3pm works']"},{"user_says":"Check request 4821 with that barber","agent_call":{"tool":"get_conversation","arguments":{"reference":"4821","business_number":"96890000001"}},"returns":"the thread for reference #4821 at that business"}],"user_query_examples":[{"user_says":"Did the salon reply about Sara's booking?","agent_call":{"tool":"get_conversation","arguments":{"conversation_id":"conv_1a2b3c4d"}},"returns":"state=awaiting_reply, reply_count=1, messages=[out: request, in: 'yes 3pm works']"},{"user_says":"Check request 4821 with that barber","agent_call":{"tool":"get_conversation","arguments":{"reference":"4821","business_number":"96890000001"}},"returns":"the thread for reference #4821 at that business"}]},{"name":"mint_key","description":"Mint a free-tier API key without email by signing agent_id + timestamp + nonce with the MACHINE_MINT_SECRET (HMAC-SHA256). Refused without that secret (invalid_request); not_configured if the operator has none set. No secret: use POST /keys/request.","readiness":{"state":"limited","summary":"Refused unless the caller signs with the machine-mint secret (HMAC-SHA256). Without it, get a free key from POST /keys/request (an emailed link)."},"when_to_use":"Use when an AI agent needs to self-provision a write-capable API key without a human email address. The caller must know the MACHINE_MINT_SECRET (available from hatchloop.dev/docs/#machine-mint).","when_not_to_use":"Do not use if the agent has a human operator who can complete the email flow at /keys/request. Do not use for paid plans — this endpoint issues free-tier keys (100 ops/day) only.","execution_profile":"sync","http":{"method":"POST","path":"/keys/mint","base_url":"https://api.hatchloop.dev"},"compliance_constraints":[],"input_schema":{"type":"object","required":["agent_id","timestamp","nonce","signature"],"properties":{"agent_id":{"type":"string","description":"A stable unique identifier for this agent (e.g. a UUID). The issued key is deterministically tied to this ID."},"timestamp":{"type":"integer","description":"Unix epoch seconds at signing time. Must be within 60s of server time."},"nonce":{"type":"string","description":"Random value (UUID or hex). Prevents replay attacks — use a fresh nonce each call."},"signature":{"type":"string","description":"HMAC-SHA256(agent_id + str(timestamp) + nonce, MACHINE_MINT_SECRET) as lowercase hex. The HMAC input is the raw concatenation with no separators."}}},"output_schema":{"type":"object","properties":{"ok":{"type":"boolean"},"key":{"type":"string","description":"The API key to use as X-Agent-Identity header."},"key_id":{"type":"string"},"expires_at":{"type":"string","description":"ISO date (YYYY-MM-DD)."},"tier":{"type":"string","enum":["free"]},"daily_limit":{"type":"integer","description":"Gated operations allowed per day."},"usage":{"type":"string"}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":100,"p95_ms":500},"idempotency":{"safe_to_retry":true,"key":"agent_id — the same agent_id always resolves to the same key_id"},"failure_modes":[{"reason_code":"invalid_request","retriable":false,"meaning":"Signature verification failed or timestamp is outside the 60s window.","agent_action":"Recompute the HMAC with the correct secret and a fresh timestamp+nonce."},{"reason_code":"not_configured","retriable":false,"meaning":"MACHINE_MINT_SECRET is not set on this server.","agent_action":"Contact hello@hatchloop.dev — the endpoint is not yet enabled."}],"examples":[{"user_says":"I need an API key to call AgentBroker tools","agent_call":{"tool":"mint_key","arguments":{"agent_id":"my-agent-abc123","timestamp":1725100000,"nonce":"4f8a2c1d","signature":"<HMAC-SHA256(agent_id+timestamp+nonce, MACHINE_MINT_SECRET)>"}},"returns":"ok=true, key=<JWT>, expires_at=2026-11-28, tier=free, daily_limit=100"}]},{"name":"lookup_us_contracts","description":"Search US federal contract awards by company (recipient) name using the free USASpending.gov public API. Returns the top awards sorted by dollar amount: award ID, recipient name, award amount USD, awarding agency, NAICS code/description, and period of performance. Zero upstream cost, no key required. Data covers 2020-2026 procurement contracts.","when_to_use":"Use when you need to know whether a company is a US federal contractor, which government agencies have awarded it contracts, the dollar value and NAICS sector of those contracts, and the period of performance. Useful for supplier due-diligence, vendor qualification, competitive intelligence, and import/trade research. The target demand: \"us import data api\", \"supplier lookup api\", \"company trade records\", \"who has government contracts\", \"federal contractor search\".","when_not_to_use":"Do not use for non-US companies (USASpending.gov only covers US federal contracts). Do not use as an exhaustive financial-risk or sanctions screen -- use verify_company_record and screen_sanctions for those. Do not use for state/local government contracts (federal only).","execution_profile":"sync","compliance_constraints":[],"input_schema":{"type":"object","required":["company_name"],"properties":{"company_name":{"type":"string","description":"Company or recipient name to search for in US federal contract awards (e.g. \"Lockheed Martin\", \"Booz Allen Hamilton\", \"Palantir Technologies\")."},"max_results":{"type":"integer","default":5,"minimum":1,"maximum":10,"description":"Maximum number of contract awards to return (sorted by award amount descending). Default: 5, max: 10."}}},"output_schema":{"type":"object","properties":{"status":{"type":"string","enum":["found","not_found","unavailable"]},"queried_name":{"type":"string"},"source":{"type":"string"},"total_in_result_set_usd":{"type":"number"},"awards":{"type":"array","items":{"type":"object","properties":{"award_id":{"type":"string"},"recipient_name":{"type":"string"},"award_amount_usd":{"type":"number"},"awarding_agency":{"type":"string"},"naics_code":{"type":"string"},"naics_description":{"type":"string"},"description":{"type":"string"},"period_start":{"type":"string"},"period_end":{"type":"string"}}}}}},"cost_model":{"basis":"free","unit_price_usd":0.0,"notes":"No key required, unmetered."},"slo":{"p50_ms":1200,"p95_ms":5000},"idempotency":"read-only","failure_modes":[{"reason_code":"bad_input","retriable":false,"meaning":"company_name is empty or missing.","agent_action":"Supply a non-empty company_name."},{"reason_code":"partial_lookup","retriable":true,"meaning":"USASpending.gov was unreachable on this call.","agent_action":"Retry; the upstream has SLA issues occasionally."}],"examples":[{"label":"Look up federal contracts for a major contractor","input":{"company_name":"Booz Allen Hamilton","max_results":3},"output":{"status":"found","total_in_result_set_usd":450000000.0,"awards":[{"award_id":"EXAMPLE-001","recipient_name":"BOOZ ALLEN HAMILTON INC.","award_amount_usd":450000000.0,"awarding_agency":"Department of Defense","naics_code":"541511","naics_description":"Custom Computer Programming Services","period_start":"2022-01-01","period_end":"2025-12-31"}]}}],"user_query_examples":[{"user_says":"Does Palantir have US government contracts?","agent_call":{"tool":"lookup_us_contracts","arguments":{"company_name":"Palantir Technologies"}}},{"user_says":"What federal contracts does Booz Allen Hamilton have?","agent_call":{"tool":"lookup_us_contracts","arguments":{"company_name":"Booz Allen Hamilton","max_results":5}}},{"user_says":"Find US import supplier data for Lockheed Martin","agent_call":{"tool":"lookup_us_contracts","arguments":{"company_name":"Lockheed Martin"}}},{"user_says":"Which government agencies are customers of SAIC?","agent_call":{"tool":"lookup_us_contracts","arguments":{"company_name":"SAIC","max_results":10}}}]}],"components":{"OutcomeReceipt":{"type":"object","properties":{"operation_id":{"type":"string"},"status":{"type":"string","enum":["success","partial","failure","pending_async"]},"reason_code":{"type":"string"},"human_message":{"type":"string"},"result":{"type":"object"},"cost":{"type":"object","properties":{"amount":{"type":"number"},"currency":{"type":"string"},"basis":{"type":"string"}}},"latency_ms":{"type":"integer"},"channel_used":{"type":"string"},"channel_fallback_chain":{"type":"array","items":{"type":"string"}},"estimated_completion_time":{"type":"string","format":"date-time"},"next_actions":{"type":"array","items":{"type":"string"}},"retriable":{"type":"boolean"},"trace_id":{"type":"string"}}}},"manifest_version":"0.1.0","generated_at":"2026-04-27T00:00:00Z","slo_data_freshness":"static_seed — replace with telemetry-driven values at P8","version":"0.2.12"}