For Amazon Bedrock · AgentCore · Strands Agents · Bedrock Agents

Every agent action on Bedrock,
independently judged before it executes.

Three agent actions below are shaped exactly as they leave the Bedrock stack — a Strands tool call, a Bedrock Agents action group, an AgentCore Gateway MCP call — and each one goes through the live Veridect system on this page. On your side the integration is a hook, a Lambda pre-check, or a URL change. Behind it is the whole control plane: consensus from frontier models across independent vendors, deterministic policy classes, risk routing, a hash-chained ledger, and an Ed25519-signed decision record you can verify right here.

Open the full live tour
3 seams
a Strands hook, a Lambda pre-check, or one MCP URL — your agents and your Bedrock models stay exactly as they are
1 endpoint
POST /pre-action — the same call for every path; the answer is a verdict plus a signed record
0 trust required
every decision re-derives from its recorded inputs and verifies against a published key — try it below
Where it sits

Between the agent’s decision and the tool’s execution.

Bedrock chooses the model and runs the agent. AgentCore gives it a runtime, identity, memory, tools and observability. Veridect sits at the one moment none of those were built to own: the instant before an action with consequences executes, when an independent judgment — not the model that proposed the action, not the platform that hosts it — decides whether it goes, waits for a person, or never happens, and signs the record either way.

Your agent on AWS

Proposes an action

  • Strands Agents on AgentCore Runtime
  • Bedrock Agents action groups
  • Any MCP client through AgentCore Gateway
Veridect · live control plane

Judges it before it runs

  • Deterministic scope check against the agent’s configured authority
  • Policy classes in code — money thresholds, protected data, regulated data, cumulative exposure
  • Multi-vendor model consensus with calibrated confidence and a dissent register
  • Risk routing: greenlight, escalate to a named human queue, or block
  • Hash-chained, Ed25519-signed record — written whether it passes or not
Outcome

Three doors, one record

greenlightthe tool runs; the verdict and record id travel with the call
escalateheld for a person in the queue the policy names
blocknever executes — and the refusal is on the ledger too
Three thin paths

The integration is thin. The system behind it is not.

Each path maps the call your agent was already making onto one request to POST /api/ai/consensus/pre-action: the verb, the target, the parameters, which agent is asking, and what that agent is authorized to do. Nothing about the agent, the model, or the tool changes. The verdict decides whether the original call proceeds.

PATH 01 · STRANDS AGENTS

A BeforeToolCallEvent hook

Strands fires a hook before every tool call and lets the hook cancel it with a message. The hook asks Veridect; anything other than a greenlight cancels the tool with the verdict and the record id — the agent sees why, and so does the ledger.

~24 lines · Python · no change to tools or model

Fail-closed by construction: the verdict starts as “unavailable” and only a parsed greenlight clears it; a timeout, a non-200 or a malformed body cancels the tool with the reason. Package the hook as a Strands Plugin and every agent on AgentCore Runtime picks it up with one line.

# strands_veridect.py
import os, requests
from strands import Agent
from strands.hooks import BeforeToolCallEvent

VERIDECT = os.environ["VERIDECT_URL"]
HEADERS  = {"Authorization": f"Bearer {os.environ['VERIDECT_API_KEY']}"}
SCOPE    = "may look up orders and may issue refunds up to $500 on existing orders"   # this agent's configured authority — yours to set, never the model's

def veridect_gate(event: BeforeToolCallEvent) -> None:
    verdict, record = "unavailable", ""                                  # closed until proven open
    try:
        r = requests.post(f"{VERIDECT}/api/ai/consensus/pre-action", headers=HEADERS, timeout=60, json={
            "action": event.tool_use["name"],
            "target": f"strands:{event.tool_use['name']}",
            "parameters": event.tool_use["input"],
            "callingAgent": event.agent.name,                                 # the agent object Strands hands the hook — not a model output
            "callingAgentScope": SCOPE,
            "department": "customer_service",
        })
        d = r.json() if r.status_code == 200 else {}
        verdict, record = d.get("verdict", "unavailable"), d.get("auditBundleId", "")
    except Exception:
        pass                                                               # network, timeout, parse: all stay closed
    if verdict != "greenlight":
        event.cancel_tool = f"Veridect {verdict} — record {record}"         # explicit cancel; the model sees why

agent = Agent(name="strands-support-agent", tools=[lookup_order, issue_refund])
agent.add_hook(veridect_gate)   # event type inferred from the hint
PATH 02 · BEDROCK AGENTS

A pre-check at the top of the action-group Lambda

Bedrock Agents hand each action to a Lambda with the function name and parameters. The first thing the handler does is ask Veridect; a non-greenlight returns the verdict to the agent in the normal response shape and the work never starts.

~26 lines · Python · same handler contract

Where the authority lives: the scope string is the agent’s configured authority, looked up by the agent name Bedrock puts on the invocation event — one handler, one authority per agent, none of it from the model. A read-only agent that proposes a mutation is a categorical no-authority action — the deterministic layer blocks it before any model is asked to weigh in. Watch it below.

# action_group/handler.py
import os, json
AUTHORITY = json.loads(os.environ["AGENT_AUTHORITY_JSON"])      # {"bedrock-order-status-agent": "read-only: may look up order status and tracking",
                                                             #  "bedrock-ap-agent": "may schedule payments on approved invoices below the dual-approval threshold"}
def handler(event, context):
    params = {p["name"]: p["value"] for p in event.get("parameters", [])}
    agent = event["agent"]["name"]                                # set by Bedrock on the invocation event — not a parameter the model fills in
    scope = AUTHORITY.get(agent)
    if scope is None:
        return respond(event, "Not executed — no configured authority for this agent.")   # never asked, never run
    verdict, record = "unavailable", ""                              # closed until proven open
    try:
        d = veridect_pre_action({
            "action": event["function"],
            "target": f"bedrock-agents:{event['actionGroup']}",
            "parameters": params,
            "callingAgent": agent,
            "callingAgentScope": scope,                                # its configured authority, in words
            "department": "customer_service",
        })
        verdict, record = d.get("verdict", "unavailable"), d.get("auditBundleId", "")
    except Exception:
        pass                                                       # network, timeout, parse: all stay closed
    if verdict != "greenlight":
        return respond(event, f"Not executed — Veridect {verdict} (record {record}).")
    return respond(event, do_the_work(event["function"], params))

def respond(event, text):
    return {"messageVersion": "1.0", "response": {
        "actionGroup": event["actionGroup"], "function": event["function"],
        "functionResponse": {"responseBody": {"TEXT": {"body": text}}}}}
PATH 03 · AGENTCORE GATEWAY

One MCP URL — no agent code at all

AgentCore Gateway exposes your tools as an MCP endpoint. Register that endpoint as a Veridect upstream once, then point the agent’s MCP client at Veridect instead. Every tools/call is judged in flight; tools/list, initialize and everything else pass straight through. A refused call is never forwarded.

0 lines of agent code · one registration, one URL

Identity on the wire: the agent’s identity, workflow id and business context ride in params._meta["veridect/…"] — unsigned, that is the caller’s own claim, and the decision record marks it as such; a tenant can require a signed Ed25519 identity envelope on every call, and an unsigned call is then refused inside the protocol. Both outcomes run live below.

# 1) once — register the AgentCore Gateway as an upstream (admin call)
POST /api/ai/consensus/mcp/upstreams/{tenant}
{ "upstreamId": "agentcore-prod",
  "url": "https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/mcp",
  "enabled": true }

# 2) the agent's MCP client — before
MCP_URL = "https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/mcp"

# 2) the agent's MCP client — after
MCP_URL = "https://<your-veridect-host>/api/mcp/gateway/agentcore-prod"
HEADERS = {
  "Authorization":            f"Bearer {VERIDECT_API_KEY}",       # your Veridect tenant
  "X-Upstream-Authorization": f"Bearer {agentcore_access_token}", # forwarded to the Gateway as Authorization
}

# 3) what the agent sees on a greenlight: the upstream's own result, plus
#    result._meta["veridect/verdict"] and result._meta["veridect/bundleId"]
#    on escalate / block: a JSON-RPC error (-32003 / -32004) carrying the
#    verdict and the record id — and the Gateway never receives the call.
Run it live

Four Bedrock-shaped actions, through the live system, now.

Each card sends the exact request the hook, the Lambda, or the gateway would send, to the live Veridect system on a shared sandbox tenant. The verdicts are real multi-model decisions made while you wait; the records are written to the ledger and signed; the Verify button re-derives the verdict from the recorded inputs and checks the signature against the published key. Expected outcomes are stated in advance — the engine decides.

Ready. Each decision takes a few seconds while the model roster deliberates.
LIVE 01 · PATH 01 · STRANDS HOOK

Refund of $120 on an existing order

A Strands support agent on AgentCore Runtime calls issue_refund for a damaged item. Its configured authority: “may look up orders and may issue refunds up to $500 on existing orders.”

Expected: greenlight — inside authority, no policy class fires, the roster agrees. The hook lets the tool run, and the record id rides along.

Waiting. Request shape: the Strands hook’s JSON, verbatim.
LIVE 02 · PATH 02 · BEDROCK AGENTS LAMBDA

A read-only agent tries to change a shipping address

A Bedrock Agents order-status agent invokes its action group with update_shipping_address. Its configured authority: “read-only: may look up order status and tracking.”

Expected: block — a read-only agent proposing a mutation is a categorical no-authority action; the deterministic scope check decides, the models are consulted for the record, and the Lambda returns the verdict instead of doing the work.

Waiting. Request shape: the Lambda event, mapped.
LIVE 03 · PATH 02 · BEDROCK AGENTS LAMBDA

Schedule a $48,000 payment to an approved vendor

An accounts-payable agent, inside its authority (“may read invoices and may schedule payments to approved vendors”), proposes a payment above this tenant’s policy limit of $10,000.

Expected: escalate — the deterministic dollar_threshold policy class fires and routes the action to the senior-officer queue. Authorized but consequential actions escalate to a person; they are never silently blocked and never silently allowed.

Waiting. Request shape: the Lambda event, mapped.
LIVE 04 · PATH 03 · AGENTCORE GATEWAY → MCP

The same tools/call, two tenants, two outcomes

A JSON-RPC tools/call for lookup_policy_limit goes through the live Veridect MCP gateway to a sample tool server that counts what it actually receives. First on the shared sandbox tenant; then on a tenant that requires a signed identity envelope, sent without one.

Expected: first call forwarded, the tool’s own hit counter goes up by one and the result carries _meta["veridect/bundleId"]; second call refused inside the protocol (-32004 identity_not_presented), counter unchanged, refusal on the ledger.

Waiting. Request shape: JSON-RPC 2.0, verbatim.

What on this page is live, and what is illustrative

Live: every verdict, confidence, dissent register, policy class, escalation route, ledger write, hash chain, Ed25519 signature, MCP forwarding decision and verification result above comes from the production Veridect system on a shared sandbox tenant — the same endpoints an integrator calls. The consensus roster is four frontier providers from independent vendors with a decisive-verdict early stop, so a decision on this surface typically records three; the models are named in each record’s dissent register. The $10,000 escalation limit is this sandbox tenant’s policy; in your tenant every threshold is yours.

Illustrative: the agent side. No Amazon Bedrock, AgentCore or Strands process is invoked from this page; each card sends the exact request the hook, Lambda pre-check or gateway chain would send, so what you watch is the decision those integrations would receive. The code on this page is the integration as written for the current Strands hook API and the Bedrock Agents action-group contract; the AgentCore Gateway URL shape is a placeholder for your own.

Verification proves that the enforcement decision re-derives from the recorded inputs and that the record is unmodified and signed by the published key. It does not re-run the models: the consensus summary is attested through the recorded dissent register and verifier-text hash, and disclosed as such in the proof itself.

Amazon Bedrock, Amazon Bedrock AgentCore, Strands Agents and AWS are trademarks of Amazon.com, Inc. or its affiliates. Veridect is an independent company and is not affiliated with or endorsed by Amazon Web Services.

Five questions, answered for a Bedrock team

The short version.

How does this help?

It lets agents on Bedrock into the workflows that carry consequences — money, customers, patients, regulators — because an independent judgment stands in front of each action and a signed record stands behind it. The model that proposes the action is never the one that approves it.

How do I integrate it?

One of the three paths above: a Strands hook, a pre-check in the action-group Lambda, or one MCP URL in front of AgentCore Gateway. Your models, agents and tools stay as they are. It runs where you say, on your keys.

How long does it take?

The system is live today. A private sandbox on your own policy thresholds in a day once you say go; production typically about two weeks, with the pace set mostly on your side — security review, keys, access. Ours is ready on day one.

How does this make money?

Three levers, none of them invented here: revenue held back because agents could not be trusted with the consequential step; cost stopped on human review of actions a signed record now settles; losses not taken on the actions that should never have executed. Your own number comes out of the sandbox.

Why you and not a big well-known company?

Because the judgment has to be independent of the model and of the platform to be worth anything to an auditor — a provider grading its own model is self-governance. Veridect is a separate control plane with its own ledger and keys, validated by an external red team on scope-violation semantics, and verifiable offline. Try to forge a record on the live tour; the engine refuses it.

Test-drive it yourself.

Run the four actions above, verify the records, then take the full live tour — identity envelopes, delegation chains, cross-agent exposure, the fleet layer, and the forgery the engine refuses. Seven minutes, open access.

Prefer to see it on your own scenarios? Paste one on the pre-action console — or write to lrussell@veridect.ai and a private sandbox on your own thresholds follows in a day.

The same control plane, built the same way for Snowflake, Microsoft, ServiceNow, CrowdStrike, Rubrik, Salesforce, Databricks, Okta and Google Cloud — one engine behind all ten pages, each run live. All ten platforms →