Sessions & attribution
Use one SDK session for one conversation or autonomous run.
session = cx.session(
agent="your-registered-agent-reference",
mcp_session_id="conversation-8472",
end_user_subject="user-193",
)
Reuse this handle for every model and MCP call in that run. Do not create a new session for every tool call.
The four identities
Agent is the registered external agent. Its capabilities, toolkit grants, and API-key scopes govern what the runtime can do.
End-user subject is the stable opaque identifier for the person the agent acts for. Use an identifier from your own account system. Keep it stable for that user, distinct across users, and free of unnecessary personal data.
Session ID is your application's conversation or run ID. Pass the same mcp_session_id for every turn that belongs together.
Objective is the overall task being performed inside a session. Pass the same objective to the search, schema, and invoke meta-tools for one task.
End-user subject
For API-key authentication, end_user_subject is required:
session = cx.session(
agent="support-agent",
mcp_session_id="support-chat:8472",
end_user_subject="user-193",
)
The subject is used for attribution and governance. It does not create a CortexHub login for that person. Do not use a display name or email address when an opaque internal identifier is available.
end_user_display_hint is optional text shown on consent surfaces. It is presentation metadata, not an identity or authorization input.
Grouping model
Session: conversation-8472
Trace: Resolve the billing issue
Span: search available tools
Span: load tool schemas
Span: invoke billing tool
Trace: Explain the result
Span: invoke messaging tool
The session ID groups the conversation or run. The objective groups one task within that session. Each governed invocation is recorded under its objective.
Keep the objective identical for search, schema, and invoke calls in one task.
Model and MCP calls in one session
session = cx.session(
agent="support-agent",
mcp_session_id="support-chat:8472",
end_user_subject="user-193",
)
reply = session.llm.responses.create(
model="cortexhub/auto",
input="Find the customer's latest invoice and explain its status.",
)
connection = session.mcp
The session ID is carried to both model and MCP connections so the activity can be correlated.
If no session ID is supplied
CortexHub can process a request without a caller-supplied session ID, but the application cannot reliably group multiple conversations that way. Provide a stable mcp_session_id whenever multi-turn grouping matters.
OAuth sessions
With a programmatic member credential, the authenticated member is the principal:
session = Cortexhub(
client_id="...",
client_secret="...",
).session(
agent="support-agent",
mcp_session_id="support-chat:8472",
conversation_title="Billing issue",
last_user_message="Why was I charged twice?",
)
conversation_title and last_user_message are optional OAuth context. end_user_subject and end_user_display_hint apply to the API-key path.
Approvals
When a governed call requires the end user's approval, the result comes back parked with an approval_id and the action's presentation. Show it in your own UI and relay the decision with session.decide(approval_id, decision, note), then poll the task with the same MCP connection until it is terminal. Keep the same session and objective while waiting so the approval remains attached to the original run. See Approvals.