Skip to content

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

list_callbacks(agent_id)

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]]

callbacks.

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]

error trace.

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(),
        }