Callbacks
Callbacks manages the Python code callbacks that run at various points in an agent's lifecycle. CXAS supports six callback types:
- before_model_callbacks — run before the LLM is called (great for injecting context or sanitizing input)
- after_model_callbacks — run after the LLM responds (useful for post-processing or logging)
- before_agent_callbacks — run when an agent is about to handle a turn
- after_agent_callbacks — run after an agent completes its turn
- before_tool_callbacks — run before a tool is executed
- after_tool_callbacks — run after a tool returns a result
Use this class when you need to programmatically read or update callback code — for example, syncing callback functions from a local code repository to CXAS, or auditing what callbacks are active on each agent.
Quick Example
from cxas_scrapi import Callbacks, Agents
app_name = "projects/my-project/locations/us/apps/my-app-id"
callbacks = Callbacks(app_name=app_name)
# List callbacks for a specific agent (returns a dict of {type: [callbacks]})
agents = Agents(app_name=app_name)
agent = agents.list_agents()[0] # Get the first agent
agent_callbacks = callbacks.list_callbacks(agent.name)
for cb_type, cb_list in agent_callbacks.items():
for cb in cb_list:
print(f"{cb_type}: {cb.description} (disabled={cb.disabled})")
Reference
Callbacks
Callbacks(app_name, **kwargs)
Bases: Agents
Core Class for managing Agent Callback Resources.
Initializes the Callbacks client.
Parameters:
| Name | Type | Description | Default |
app_name | str | The full resource name of the parent App (projects/PROJECT_ID/locations/LOCATION/apps/APP_ID). | required |
Source code in src/cxas_scrapi/core/callbacks.py
| def __init__(self, app_name: str, **kwargs):
"""Initializes the Callbacks client.
Args:
app_name: The full resource name of the parent App
(projects/PROJECT_ID/locations/LOCATION/apps/APP_ID).
"""
super().__init__(app_name=app_name, **kwargs)
self.resource_type = "callbacks"
# Maps shorthand callback types to the exact field names in the
# Agent proto
self.callback_map = {
"before_model": "before_model_callbacks",
"after_model": "after_model_callbacks",
"before_tool": "before_tool_callbacks",
"after_tool": "after_tool_callbacks",
"before_agent": "before_agent_callbacks",
"after_agent": "after_agent_callbacks",
}
|
list_callbacks
Lists callbacks attached to a specific agent.
Returns:
| Type | Description |
Dict[str, List[Callback]] | A dictionary mapping the callback field name to a list of its |
Dict[str, List[Callback]] | |
Source code in src/cxas_scrapi/core/callbacks.py
| def list_callbacks(self, agent_id: str) -> Dict[str, List[types.Callback]]:
"""Lists callbacks attached to a specific agent.
Returns:
A dictionary mapping the callback field name to a list of its
callbacks.
"""
agent = self.get_agent(agent_id)
return {
"before_model_callbacks": list(agent.before_model_callbacks),
"after_model_callbacks": list(agent.after_model_callbacks),
"before_tool_callbacks": list(agent.before_tool_callbacks),
"after_tool_callbacks": list(agent.after_tool_callbacks),
"before_agent_callbacks": list(agent.before_agent_callbacks),
"after_agent_callbacks": list(agent.after_agent_callbacks),
}
|
get_callback
get_callback(agent_id, callback_type, index=0)
Gets a specific callback from an agent by its index.
Source code in src/cxas_scrapi/core/callbacks.py
| def get_callback(
self, agent_id: str, callback_type: str, index: int = 0
) -> Optional[types.Callback]:
"""Gets a specific callback from an agent by its index."""
field_name = self.callback_map.get(callback_type)
if not field_name:
raise ValueError(f"Invalid callback type: {callback_type}")
agent = self.get_agent(agent_id)
callbacks = list(getattr(agent, field_name))
if 0 <= index < len(callbacks):
return callbacks[index]
return None
|
create_callback
create_callback(agent_id, callback_type, code, description='', disabled=False)
Appends a new callback to the specific callback field on the Agent.
Source code in src/cxas_scrapi/core/callbacks.py
| def create_callback(
self,
agent_id: str,
callback_type: str,
code: Union[Callable, str],
description: str = "",
disabled: bool = False,
) -> types.Agent:
"""Appends a new callback to the specific callback field on the
Agent."""
field_name = self.callback_map.get(callback_type)
if not field_name:
raise ValueError(f"Invalid callback type: {callback_type}")
# Fetch the entire agent
agent = self.get_agent(agent_id)
# Parse the code into a string
python_code = self._format_python_code(callback_type, code)
# Create the new callback proto
new_callback = types.Callback(
python_code=python_code, description=description, disabled=disabled
)
# We must append the proto to the specific repeated field list
# Since protobuf handles assignment, we can extend the existing list
getattr(agent, field_name).append(new_callback)
# Use field mask so we only update the specific callback field
mask = field_mask_pb2.FieldMask(paths=[field_name])
request = types.UpdateAgentRequest(agent=agent, update_mask=mask)
return self.client.update_agent(request=request)
|
update_callback
update_callback(agent_id, callback_type, index, code=None, description=None, disabled=None)
Updates an existing callback on the agent by its index.
Source code in src/cxas_scrapi/core/callbacks.py
| def update_callback(
self,
agent_id: str,
callback_type: str,
index: int,
code: Union[Callable, str] = None,
description: str = None,
disabled: bool = None,
) -> types.Agent:
"""Updates an existing callback on the agent by its index."""
field_name = self.callback_map.get(callback_type)
if not field_name:
raise ValueError(f"Invalid callback type: {callback_type}")
agent = self.get_agent(agent_id)
callbacks = getattr(agent, field_name)
if not (0 <= index < len(callbacks)):
raise IndexError(
f"Callback index {index} out of range for {field_name}"
)
if code is not None:
callbacks[index].python_code = self._format_python_code(
callback_type, code
)
if description is not None:
callbacks[index].description = description
if disabled is not None:
callbacks[index].disabled = disabled
mask = field_mask_pb2.FieldMask(paths=[field_name])
request = types.UpdateAgentRequest(agent=agent, update_mask=mask)
return self.client.update_agent(request=request)
|
delete_callback
delete_callback(agent_id, callback_type, index)
Deletes a callback from the agent by its index.
Source code in src/cxas_scrapi/core/callbacks.py
| def delete_callback(
self, agent_id: str, callback_type: str, index: int
) -> types.Agent:
"""Deletes a callback from the agent by its index."""
field_name = self.callback_map.get(callback_type)
if not field_name:
raise ValueError(f"Invalid callback type: {callback_type}")
agent = self.get_agent(agent_id)
callbacks = getattr(agent, field_name)
if not (0 <= index < len(callbacks)):
raise IndexError(
f"Callback index {index} out of range for {field_name}"
)
# Remove the specific element
del callbacks[index]
mask = field_mask_pb2.FieldMask(paths=[field_name])
request = types.UpdateAgentRequest(agent=agent, update_mask=mask)
return self.client.update_agent(request=request)
|
execute_callback staticmethod
execute_callback(callback_func, mock_session_input)
Executes a localized python callback function hermetically against a mock session.
Parameters:
| Name | Type | Description | Default |
callback_func | Union[Callable, str] | The logic to execute. Either a Callable or a string. | required |
mock_session_input | Dict[str, Any] | The dummy session state/input corresponding to what the CES engine usually provides. | required |
Returns:
| Type | Description |
Dict[str, Any] | A dictionary containing either the returned dictionary update or |
Dict[str, Any] | |
Source code in src/cxas_scrapi/core/callbacks.py
| @staticmethod
def execute_callback(
callback_func: Union[Callable, str], mock_session_input: Dict[str, Any]
) -> Dict[str, Any]:
"""Executes a localized python callback function hermetically against
a mock session.
Args:
callback_func: The logic to execute. Either a Callable or a string.
mock_session_input: The dummy session state/input
corresponding to what the CES engine usually provides.
Returns:
A dictionary containing either the returned dictionary update or
error trace.
"""
if isinstance(callback_func, Callable):
try:
code_str = textwrap.dedent(inspect.getsource(callback_func))
except OSError as e:
raise ValueError(
"Could not extract Python source code. Pass as a string "
"instead."
) from e
func_name = callback_func.__name__
else:
code_str = callback_func
# Basic parsing to find the "def FuncName(...):" signature
match = re.search(r"def (\w+)\s*\(", code_str)
if match:
func_name = match.group(1)
else:
raise ValueError(
"Could not determine the function name from the provided "
"code string."
)
# Prepare a restricted execution environment
exec_globals = {}
try:
# Execute the string into our globals namespace
exec(code_str, exec_globals)
except Exception as e:
return {"error": f"Compilation failed: {str(e)}"}
if func_name not in exec_globals:
return {
"error": f"Function {func_name} not found after executing "
f"the code block."
}
# Call the function hermetically
try:
# The execution signature usually accepts a `session` argument
# containing the state dict
result = exec_globals[func_name](mock_session_input)
return {"success": True, "result": result}
except Exception as e:
return {
"error": f"Execution failed: {str(e)}",
"traceback": traceback.format_exc(),
}
|