Edictum
Edictum Console

Connecting Agents

Connect your Python agents to Edictum Console for live contract updates, audit event streaming, and human-in-the-loop approvals.

AI Assistance

Right page if: you need to connect a Python agent to Edictum Console using `Edictum.from_server()` and the `edictum[server]` SDK. Wrong page if: you want to use edictum without a server (see https://docs.edictum.ai/docs/quickstart) or route bundles to agents with rules (see https://docs.edictum.ai/docs/console/agent-assignment). Gotcha: the `env` parameter must match the API key's environment scope -- `edk_production_...` requires `env="production"` or the connection fails.

Connect your Python agents to Edictum Console for live contract updates, audit event streaming, and human-in-the-loop approvals.

Install the SDK

pip install edictum[server]

Requires Python 3.11+. The [server] extra adds the SDK classes that communicate with the console.

Connect with from_server()

from edictum import Edictum

guard = await Edictum.from_server(
    url="http://localhost:8000",             # Console URL
    api_key="edk_production_CZxKQvN3mHz...", # From Dashboard > API Keys
    agent_id="my-agent",                     # Unique identifier for this agent
    env="production",                        # Optional; defaults to "production"
    bundle_name="my-contracts",              # Bundle to subscribe to (optional)
    tags={"team": "platform", "tier": "1"},  # Tags for assignment rules (optional)
    auto_watch=True,                         # Optional; keep SSE watcher enabled
)

# Use guard.run() exactly like local edictum
result = await guard.run("read_file", {"path": "data.csv"}, read_file)

Parameters

ParameterRequiredDescription
urlYesConsole base URL
api_keyYesAPI key from the dashboard (e.g. edk_production_...)
agent_idYesUnique identifier for this agent instance
envNoEnvironment name (should match the API key scope). Defaults to "production".
bundle_nameNoSpecific bundle to subscribe to. If omitted, resolved via assignment rules.
tagsNoDict of key-value tags for assignment rule matching
auto_watchNoDefaults to true. Must remain true when bundle_name is omitted so the agent can receive its assignment and updates over SSE.
allow_insecureNoDefaults to false. Set to true to allow plaintext HTTP connections to non-loopback hosts. Logs a warning when enabled.

HTTPS enforcement

from_server() requires HTTPS for non-loopback hosts by default. Connecting to a remote host over http:// raises ValueError unless allow_insecure=True is passed.

Loopback addresses are always exempt: http://localhost, http://127.0.0.1, and http://[::1] connect without error regardless of allow_insecure.

# Production remote host — use HTTPS
guard = await Edictum.from_server(
    url="https://console.example.com",
    api_key="edk_production_CZxKQvN3mHz...",
    agent_id="my-agent",
)

# Local dev — loopback is always exempt
guard = await Edictum.from_server(
    url="http://localhost:8000",
    api_key="edk_production_CZxKQvN3mHz...",
    agent_id="my-agent",
)

# Internal HTTP host — opt in explicitly (logs a warning)
guard = await Edictum.from_server(
    url="http://internal-console:8000",
    api_key="edk_production_CZxKQvN3mHz...",
    agent_id="my-agent",
    allow_insecure=True,
)

What Happens on Connect

  1. Agent registers -- the SDK sends a registration request. The console creates or updates the agent's record in agent_registrations with its metadata, tags, and last-seen timestamp.

  2. Bundle fetch -- the SDK calls GET /api/v1/bundles/{name}/current?env={env} to fetch the currently deployed contract bundle. The response includes the YAML (base64-encoded) and Ed25519 signature.

  3. SSE subscription -- the SDK opens a persistent connection to GET /api/v1/stream. It receives contract_update events when contracts are redeployed, and assignment_changed events when the agent's bundle assignment changes.

  4. Audit sink starts -- the ServerAuditSink begins batching tool call events and posting them to POST /api/v1/events.

  5. Approval backend ready -- the ServerApprovalBackend is configured to create and poll approvals via the console API.

SDK Classes

The from_server() call configures these components internally:

ClassPurposeKey Settings
EdictumServerClientHTTP client for all API callstimeout=30, max_retries=3
ServerAuditSinkBatched event ingestionbatch_size=50, flush_interval=5.0s, max_buffer_size=10000
ServerApprovalBackendHITL approval create + pollpoll_interval=2.0s
ServerBackendServer-side session stateKey-value store, atomic increment
ServerContractSourceSSE contract subscriptionreconnect_delay=1.0s, max_reconnect_delay=60.0s

Graceful Fallback

If the console is unreachable on startup, fall back to local contracts:

from edictum import Edictum

try:
    guard = await Edictum.from_server(
        url="http://localhost:8000",
        api_key="edk_production_CZxKQvN3mHz...",
        agent_id="my-agent",
        env="production",
    )
except Exception:
    # Server down -- use local contracts
    guard = Edictum.from_yaml("contracts.yaml")

Important: Edictum fails closed. If the server becomes unreachable after connection, errors propagate and tool calls are denied. The agent never silently passes when the server is down.

Multiple Agents

Each agent needs a unique agent_id. The API key can be shared across agents in the same environment:

# Agent 1
guard_1 = await Edictum.from_server(
    url="http://localhost:8000",
    api_key="edk_production_CZxKQvN3mHz...",
    agent_id="research-agent",
    env="production",
)

# Agent 2
guard_2 = await Edictum.from_server(
    url="http://localhost:8000",
    api_key="edk_production_CZxKQvN3mHz...",
    agent_id="ops-agent",
    env="production",
)

Both agents appear separately in the dashboard's Agents page.

Tags for Assignment Rules

Tags are key-value pairs attached to the agent registration. Assignment rules can match on tags to route specific bundles:

guard = await Edictum.from_server(
    url="http://localhost:8000",
    api_key="edk_production_CZxKQvN3mHz...",
    agent_id="prod-platform-agent",
    env="production",
    tags={"team": "platform", "tier": "1", "region": "us-east"},
)

See Agent Assignment for how to create rules that match on tags.

Framework Adapters

After connecting, use the guard with any supported framework adapter. The adapter API is identical to local edictum:

# LangChain
from edictum.adapters.langchain import LangChainAdapter
adapter = LangChainAdapter(guard)
tool_node = ToolNode(tools=tools, wrap_tool_call=adapter.as_tool_wrapper())

# CrewAI
from edictum.adapters.crewai import CrewAIAdapter
adapter = CrewAIAdapter(guard)
adapter.register()

# OpenAI Agents SDK
from edictum.adapters.openai_agents import OpenAIAgentsAdapter
adapter = OpenAIAgentsAdapter(guard)
input_gr, output_gr = adapter.as_guardrails()

All eight adapters work with server-connected guards. See the edictum adapter docs for details.

API Key Management

API key management in the console

Troubleshooting

ProblemFix
401 Unauthorized on connectAPI key is invalid or revoked. Create a new one in Dashboard > API Keys.
Agent shows "Last Seen: never"Check that events are being sent -- the SDK needs guard.run() calls to generate events.
Bundle not found on connectDeploy a bundle first in Dashboard > Contracts > Bundles. Or set bundle_name to match an existing bundle.
SSE disconnects frequentlyCheck network stability. The SDK reconnects automatically with exponential backoff (1s to 60s).
env mismatch errorThe env parameter must match the API key's environment scope (e.g. edk_production_... requires env="production").
ValueError: HTTPS requiredConsole URL uses http:// with a non-loopback host. Use https:// or pass allow_insecure=True (logs a warning).

Next Steps

Last updated on

On this page