C

Cohere runtime authorization

Wrap Cohere tool use with Veto. Each governed tool call, including calls produced from retrieved documents, is evaluated before dispatch: allow, review, or deny, with an exportable decision record per governed decision.

Why Cohere needs guardrails

Cohere supports tool-augmented enterprise workflows. Its tool_use API returns a tool_plan alongside the tool_calls. The model explains what it intends to do, then names the calls. The plan is reasoning. The calls are executable side effects. The API does not enforce a boundary between them; your code does.

Cohere's RAG mode combines retrieved documents and tools in a single turn. Retrieved content can carry adversarial instructions that steer the tool plan. Without guardrails at tool_results time, poisoned documents drive real side effects.

Plan ≠ permission

The Cohere tool_plan describes intent in natural language. It is not an approval. The tool_calls run regardless.

RAG injection paths

Retrieved documents fed via the documents= parameter can contain instructions the model may follow when planning tool use.

Enterprise stakes

Cohere is deployed for contract review, customer ops, and finance. Tool calls touch high-value records.

Before and after Veto

The left tab shows standard Cohere tool use. The model returns tool_calls; your code executes them and feeds tool_results back. The right tab adds Veto between the model's decision and the dispatch. Same agent, same tools, each governed call evaluated against policy first.

py
import os
import cohere

co = cohere.ClientV2()

tools = [
    {
        "type": "function",
        "function": {
            "name": "lookup_contract",
            "description": "Read a customer contract from the legal datastore",
            "parameters": {
                "type": "object",
                "properties": {
                    "contract_id": {"type": "string"},
                },
                "required": ["contract_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "amend_contract",
            "description": "Apply an amendment to a customer contract",
            "parameters": {
                "type": "object",
                "properties": {
                    "contract_id": {"type": "string"},
                    "clause": {"type": "string"},
                    "new_text": {"type": "string"},
                },
                "required": ["contract_id", "clause", "new_text"],
            },
        },
    },
]

response = co.chat(
    model=os.environ["COHERE_MODEL"],
    messages=[{"role": "user", "content": user_message}],
    tools=tools,
)

# Cohere Chat V2 returns tool_plan + tool_calls. Your code runs them.
# An adversarial customer email can steer amend_contract.
tool_results = []
for tc in response.message.tool_calls or []:
    args = json.loads(tc.function.arguments)
    result = execute_tool(tc.function.name, args)
    tool_results.append({
        "tool_call_id": tc.id,
        "output": result,
    })

# Feed results back into Cohere for the final response
final = co.chat(
    model=os.environ["COHERE_MODEL"],
    messages=[
        *previous_messages,
        response.message,
        *[{"role": "tool", "tool_call_id": r["tool_call_id"], "content": r["output"]} for r in tool_results],
    ],
)

Tool use with RAG

Cohere's combined RAG + tool-use mode widens the prompt-injection surface. Pass the retrieved document IDs into Veto's context so policies can audit which document drove which call.

cohere_rag_with_veto.py
import os
import cohere
import json
from veto_sdk import Veto

co = cohere.ClientV2()
veto = Veto(api_key=os.environ["VETO_API_KEY"])

# Cohere's RAG + tool use: retrieved documents AND tools in one turn.
# A poisoned document can instruct the model to call a destructive tool.
# Veto guards the tool calls so retrieved instructions cannot drive side effects.
response = co.chat(
    model=os.environ["COHERE_MODEL"],
    messages=[{"role": "user", "content": user_message}],
    tools=tools,
    documents=retrieved_docs,
)

for tc in response.message.tool_calls or []:
    args = json.loads(tc.function.arguments)
    decision = veto.guard(
        tool=tc.function.name,
        arguments=args,
        context={"source": "rag", "doc_ids": [d.get("id") for d in retrieved_docs]},
    )
    if decision.decision != "allow":
        continue
    execute_tool(tc.function.name, args)

Policy configuration

Encode guardrails in declarative YAML. The same policies cover Cohere on the Cohere API, on Azure, and on Bedrock: Veto guards the tool dispatch, not the inference endpoint.

veto/policies.yaml
rules:
  - name: block_external_contract_amend
    description: Amendments require an internal user
    tool: amend_contract
    when: "!context.user_id.startsWith('internal-')"
    action: deny
    message: "Contract amendments restricted to internal staff"

  - name: approve_material_clause_changes
    description: Material clauses need legal sign-off
    tool: amend_contract
    when: args.clause in ["indemnification", "liability_cap", "termination", "data_processing"]
    action: require_approval
    approvers: [legal-ops]
    timeout: 4h

  - name: cap_clause_length
    description: Refuse unreasonably long replacement text
    tool: amend_contract
    when: args.new_text.length > 4000
    action: deny
    message: "Replacement clause exceeds 4,000 characters: submit manually"

  - name: contract_lookup_allowlist
    description: Customers can only read their own contracts
    tool: lookup_contract
    when: "!context.user_contracts.includes(args.contract_id)"
    action: deny
    message: "Contract not assigned to this user"

How Veto fits

1

Install the SDK

pip install veto-sdk cohere
2

Define policies

Create veto/policies.yaml. Use the same tool name you registered in the Cohere tools schema.

3

Guard between tool_calls and tool_results

For each governed tool_call returned by Cohere, call veto.guard() before dispatching. Feed the outcome (or denial) into the next chat call as a tool_result.

Use cases

Contract operations

A Cohere-backed agent reviews and amends customer contracts. Restrict amendments to internal users, require legal approval on material clauses, cap replacement length.

Enterprise search and act

Cohere runs RAG patterns across internal knowledge bases. Check tool calls so retrieved documents cannot steer destructive actions.

Multi-tenant data access

Allowlist customer record access by tenant. A user's agent is limited to the contracts and tickets assigned to them: enforced at the governed tool boundary, independent of the model response.

Tool plan transparency

Pass The Cohere tool_plan into Veto's context. Policies can log the plan alongside the call. Decision records capture what the model said it would do and what it tried to run.

Frequently asked questions

Does Veto work with Cohere models that emit tool calls?
Yes. Veto guards the tool dispatch path. Any Cohere model that emits tool_calls in the V2 chat API works the same way: parse the tool_calls, call veto.guard() for each, feed the outcome back as a tool_result.
What about Cohere's RAG mode with retrieved documents?
Veto handles RAG by guarding the tool calls the model produces from retrieved context. Pass the document IDs into veto.guard()'s context so policies can audit which retrieved document drove which call. Poisoned documents lose authority over high-impact downstream tools when the governed call is blocked.
Can I use Cohere on Azure or Bedrock with Veto?
Yes. Veto guards your dispatch code, not the inference endpoint. Whether Cohere is served via the Cohere API, Azure AI Foundry, or AWS Bedrock, the tool_calls have the same shape and the integration point is identical.
Does the tool_plan get included in decision records?
If you pass the tool_plan as context to veto.guard(), it is recorded with the decision. This gives compliance reviewers the model's natural-language explanation alongside the actual call for incident analysis.

Related integrations

Wrap one Cohere tool path and inspect the decision record.