Playbook: Control Where Your Tools Can Send Data
You built tools that connect your AI to the systems your team uses every day: the ERP, the carrier's shipping portal, the supplier's order API. They work. Th...
You built tools that connect your AI to the systems your team uses every day: the ERP, the carrier's shipping portal, the supplier's order API. They work. Then you notice that the tool that posts a purchase order takes a web address as a parameter, and the AI decides what goes in it. Nothing stops a confused agent, or a cleverly worded document it was asked to summarize, from pointing that tool somewhere else. This playbook walks you through making sure your tools can only talk to the systems you approved, and that email from your agents only reaches the people it should.
What you will build
By the end of this playbook, you will have:
- A custom tool that sends requests to your internal and partner systems
- A rule that limits requests to an approved list of hosts
- A second rule that closes the gap when the address is left out
- A rule that keeps agent email inside your company and your named partners
- An exception for the one team that needs to reach further
- A tested setup and a record of every attempt that was blocked
What you need before you start
- An Assist workspace where you are a workspace admin.
- An AI client connected to your workspace through an MCP server, or the chat in Assist.
- The addresses of the systems your tools should reach. For example,
erp.internal.company.com,api.carrier-partner.com, and your supplier's API host. - The email domains your agents may write to: your own, and any partners.
- A few minutes with whoever owns those systems, to confirm the list is complete.
Step 1: Build the request tool
In your AI client, describe what you need:
"Create a tool called 'partner_api_request' that sends a request to one of our partner systems. It should take a 'url' parameter, a 'method' parameter that is one of get, post, put, or delete, and an optional 'body' parameter. Credentials for each host are stored in workspace secrets, and the tool should pick the right one based on the host."
When the AI asks whether method should accept any text, say no. A fixed set of choices is easier to control, and the rule editor will offer those choices as a list.
Test the tool against something harmless:
"Use partner_api_request to get the list of open purchase orders from the ERP."
Confirm you get real data back. You now have a working tool that, as built, will send a request to any address it is given.
Step 2: List the approved hosts
Write down every host the tool should reach. Be specific about subdomains:
| System | Host | Include subdomains |
|---|---|---|
| ERP | erp.internal.company.com | No |
| Carrier portal | carrier-partner.com | Yes, they use several |
| Supplier API | api.supplier.example | No |
Subdomains matter. An entry of carrier-partner.com covers that exact host only. To cover api.carrier-partner.com and track.carrier-partner.com as well, write the entry with a dot in front: .carrier-partner.com.
Step 3: Block every host that is not on the list
In Assist, open Permissions and select the Tool Policies tab. Click New Rule.
- Under Action, select Deny.
- Under Applies to, leave Workspace.
- In Tool, type
partnerand press Tab to completepartner_api_request. - Click Add condition.
- Click Path, press Tab, and choose
url.
Because the parameter holds a web address, the editor puts the host operators first and selects url_host_not_in. That is the one you want: it matches when the address is on a host that is not in your list.
-
In Values, enter your hosts, separated by commas:
erp.internal.company.com, .carrier-partner.com, api.supplier.example -
Reason: "Requests may only go to approved partner systems."
-
Message returned to the model on deny: "That address is not an approved system. Approved systems are the ERP, the carrier portal, and the supplier API. Do not retry with a different address."
Test it under Test conditions. Click Fill from tool, then try each of these in the url value and click Run test:
| Address | Expected |
|---|---|
https://erp.internal.company.com/api/orders | Does not match, so the call is allowed |
https://track.carrier-partner.com/status | Does not match |
https://example.org/collect | Matches, so the call is blocked |
https://erp.internal.company.com.example.org/x | Matches. The host is example.org, not your ERP. |
example.org/collect | Matches. An address that cannot be read as a web address counts as off the list. |
The last two are the ones people forget. An address that merely contains your host name is not on your host, and the rule checks the host itself, not the text.
Click Create Rule.
Step 4: Close the gap when the address is missing
The rule you made matches only when url is present. If a call leaves it out, the rule does not apply. Whether that matters depends on your tool: if it falls back to a default address, a call with no url should be treated on its merits.
If url is required by the tool, you can skip this step. If it is optional, add a rule:
- Action: Deny, Applies to: Workspace, Tool:
partner_api_request. - Add a condition on
urlwith the operator missing. - Reason: "Every request must name its destination."
- Message returned to the model on deny: "Provide the full address of an approved system in the url parameter."
Click Create Rule.
Step 5: Keep destructive requests to the people who need them
Reading from a partner system is routine. Deleting from one is not. Add a rule on method:
- Action: Deny, Applies to: Workspace, Tool:
partner_api_request. - Add a condition and choose the path
method. Because the tool defines a fixed set of choices, Value shows them as a list. - Set Operator to in and tick
deleteandput. - Reason: "Only the integrations team may change or delete partner records."
- Message returned to the model on deny: "You can read and create records. Changes and deletions must be made by the integrations team."
Then add the exception above it. Click New Rule, select Allow, set Applies to to Group and pick Integrations, set Tool to partner_api_request, and under Placement choose the position directly after your host rule. The order, from the top, should be:
- Block hosts that are not approved. This applies to everyone.
- Block requests with no address.
- Allow the integrations group.
- Block
deleteandputfor everyone else.
The host rule sits above the exception on purpose. The integrations team may use any method, but only against approved systems.
Step 6: Keep agent email inside the fence
Your agents send email: exception reports, shipment updates, reconciliation summaries. Make sure those only reach your company and your named partners.
Find the tool your agents use to send email. In the rule editor, type send in Tool and press Tab to see the options. Choose the email tool, then:
-
Action: Deny.
-
Sources: tick Subagent. This rule is for agents. People sending email from chat are not affected.
-
Add a condition. Press Tab in Path and look for the recipient parameter. If recipients are a list, choose the path that ends in
[*], such asto[*], so that every recipient is checked. -
Set Operator to matches and enter a pattern that describes an address outside your approved domains. If your approved domains are
company.comandcarrier-partner.com:@(?!company\.com$|carrier-partner\.com$) -
Tick ignore case.
-
Reason: "Agents may only email the company and named partners."
-
Message returned to the model on deny: "Agents can only send email to company and partner addresses. Remove the other recipients and try again."
With a list path, the rule matches if any recipient is outside your domains. One outside address blocks the whole message, which is what you want.
Test it with a few recipient lists before you save. Include one list where every address is approved and one where a single address is not.
Step 7: Test the whole list
Select the Simulator tab and switch to Tool call. Run the checks that matter:
| Person | Source | Call | Expected |
|---|---|---|---|
| Operations member | Chat | Get from the ERP | Allowed |
| Operations member | Chat | Post to example.org | Blocked by the host rule |
| Integrations member | Chat | Delete on the carrier portal | Allowed by the group exception |
| Integrations member | Chat | Delete on example.org | Blocked by the host rule |
| Any agent | Subagent | Email to an outside address | Blocked by the email rule |
| Any person | Chat | Email to an outside address | Allowed, because the rule is limited to agents |
Read the Evaluation trace for each. If the integrations member is blocked on the carrier portal, the exception is below the method rule. Open the rule and change its Placement.
Step 8: Watch what gets blocked
Open Tool History and select Blocked. In the first week, expect a few entries. Each one is either a gap in your approved list or an attempt you are glad was stopped.
For a gap, such as a supplier that moved its API to a new host, edit the host rule and add the entry. For an attempt you want to look into, click the call to see who made it, which agent or chat it came from, and the exact address.
What you built
Your tools reach the systems you approved and nothing else. Addresses that only look like your systems are blocked. Requests that change or delete partner records are limited to the team responsible for them. Agents can send email to the company and its partners, and nowhere else. When something is blocked, the AI explains why and does not keep trying.
None of this required changing a tool. When you add a partner, you add one entry to one rule.
Where to go next
- Apply the host rule to a whole tool pack. Leave Tool blank and set Tool pack so that every tool in the pack is covered, including ones built later.
- Separate what agents may reach from what people may reach. Add a stricter host rule with Sources set to Subagent.
- Limit payload size. If a tool accepts a list of records, a condition with array_size_gt stops a request that tries to send thousands at once.
- Add judgment. Use a classifier to check whether the body of a request contains customer data before it leaves. See Using a tool as a classifier.