ComposioComposio 0.21 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
8 small wins to finish your pathNext lesson

Modifiers: control what goes in and comes out

Modifiers are functions Composio applies around direct tool calls: before_execute changes arguments, after_execute changes results.

Example
from composio import after_execute, before_execute


@before_execute(tools=["GITHUB_CREATE_AN_ISSUE"])
def label_agent_issues(tool, toolkit, params):
    params["arguments"].setdefault("labels", []).append("created-by-agent")
    return params


@after_execute(toolkits=["gmail"])
def keep_only_subjects(tool, toolkit, response):
    messages = response["data"].get("messages", [])
    response["data"] = {"subjects": [m.get("subject") for m in messages]}
    return response
Example
params = {"arguments": {"title": "Refund failed for A-1002"}}
print(label_agent_issues.apply("github", "GITHUB_CREATE_AN_ISSUE", params, "before_execute"))
print(label_agent_issues.apply("slack", "SLACK_SEND_MESSAGE", {"arguments": {"text": "hi"}}, "before_execute"))

The decorator returns a Modifier, and apply is the method the SDK calls around every direct execution, with the toolkit slug, the tool slug, the data and the modifier type. Listed tools or toolkits limit where it runs: the GitHub issue got a label, the Slack message came back unchanged.

Example
response = {"successful": True, "error": None, "data": {"messages": [{"subject": "Invoice", "body": "card 4111 1111 1111 1111"}]}}
print(keep_only_subjects.apply("gmail", "GMAIL_FETCH_EMAILS", response, "after_execute"))
print(keep_only_subjects.apply("GMAIL", "GMAIL_FETCH_EMAILS", response, "after_execute") is response)

after_execute runs on the result before your code, and so the model, sees it. This one keeps only subjects, so an email body with a card number never enters the prompt, the model's provider or your logs. The last line shows that matching is exact: "GMAIL" does not match "gmail", so the result came back untouched, the same object. Use slugs exactly as the SDK reports them, and print one real result before you rely on its shape; the messages and subject keys here are an example.

Examplewith a key
tools = composio.tools.get(user_id, tools=["GMAIL_FETCH_EMAILS"])
results = composio.provider.handle_tool_calls(user_id=user_id, response=response, modifiers=[keep_only_subjects])

Why modifiers matter for a deployment

  • Force values the model must not choose, such as a label, a repository or a sender.
  • Remove data the model does not need before it reaches a third-party model provider.
  • Change tool schemas the model sees with schema_modifier, passed to composio.tools.get.
Try it yourself
  • Write a before_execute modifier that refuses emails to addresses outside the customer's domain by raising.
  • Apply keep_only_subjects with the modifier type before_execute.
  • Read the argument types of schema_modifier in composio/core/models/_modifiers.py.
PreviousCustom tools

Little by little, you're building something great.