Skip to main content
Glama

Think About Task Adherence

think_about_task_adherence
Read-only

Assess whether you remain aligned with the original task objective, particularly after extended conversations or complex interactions, to maintain focus before making code modifications.

Instructions

Think about the task at hand and whether you are still on track. Especially important if the conversation has been going on for a while and there has been a lot of back and forth.

This tool should ALWAYS be called before you insert, replace, or delete code.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The core handler implementation for the 'think_about_task_adherence' tool. It inherits from Tool and its apply() method returns a rendered prompt for task adherence reflection.
    class ThinkAboutTaskAdherenceTool(Tool):
        """
        Thinking tool for determining whether the agent is still on track with the current task.
        """
    
        def apply(self) -> str:
            """
            Think about the task at hand and whether you are still on track.
            Especially important if the conversation has been going on for a while and there
            has been a lot of back and forth.
    
            This tool should ALWAYS be called before you insert, replace, or delete code.
            """
            return self.prompt_factory.create_think_about_task_adherence()
  • Helper method in the prompt factory that renders the specific prompt template used by the tool handler.
    def create_think_about_task_adherence(self) -> str:
        return self._render_prompt("think_about_task_adherence", locals())
  • The ToolRegistry dynamically discovers and registers all Tool subclasses, including ThinkAboutTaskAdherenceTool, by scanning subclasses in serena.tools packages. This makes the tool available for instantiation in the agent.
    @singleton
    class ToolRegistry:
        def __init__(self) -> None:
            self._tool_dict: dict[str, RegisteredTool] = {}
            for cls in iter_subclasses(Tool):
                if not any(cls.__module__.startswith(pkg) for pkg in tool_packages):
                    continue
                is_optional = issubclass(cls, ToolMarkerOptional)
                name = cls.get_name_from_cls()
                if name in self._tool_dict:
                    raise ValueError(f"Duplicate tool name found: {name}. Tool classes must have unique names.")
                self._tool_dict[name] = RegisteredTool(tool_class=cls, is_optional=is_optional, tool_name=name)
    
        def get_tool_class_by_name(self, tool_name: str) -> type[Tool]:
            return self._tool_dict[tool_name].tool_class
    
        def get_all_tool_classes(self) -> list[type[Tool]]:
            return list(t.tool_class for t in self._tool_dict.values())
    
        def get_tool_classes_default_enabled(self) -> list[type[Tool]]:
            """
            :return: the list of tool classes that are enabled by default (i.e. non-optional tools).
            """
            return [t.tool_class for t in self._tool_dict.values() if not t.is_optional]
    
        def get_tool_classes_optional(self) -> list[type[Tool]]:
            """
            :return: the list of tool classes that are optional (i.e. disabled by default).
            """
            return [t.tool_class for t in self._tool_dict.values() if t.is_optional]
    
        def get_tool_names_default_enabled(self) -> list[str]:
            """
            :return: the list of tool names that are enabled by default (i.e. non-optional tools).
            """
            return [t.tool_name for t in self._tool_dict.values() if not t.is_optional]
    
        def get_tool_names_optional(self) -> list[str]:
            """
            :return: the list of tool names that are optional (i.e. disabled by default).
            """
            return [t.tool_name for t in self._tool_dict.values() if t.is_optional]
    
        def get_tool_names(self) -> list[str]:
            """
            :return: the list of all tool names.
            """
            return list(self._tool_dict.keys())
    
        def print_tool_overview(
            self, tools: Iterable[type[Tool] | Tool] | None = None, include_optional: bool = False, only_optional: bool = False
        ) -> None:
            """
            Print a summary of the tools. If no tools are passed, a summary of the selection of tools (all, default or only optional) is printed.
            """
            if tools is None:
                if only_optional:
                    tools = self.get_tool_classes_optional()
                elif include_optional:
                    tools = self.get_all_tool_classes()
                else:
                    tools = self.get_tool_classes_default_enabled()
    
            tool_dict: dict[str, type[Tool] | Tool] = {}
            for tool_class in tools:
                tool_dict[tool_class.get_name_from_cls()] = tool_class
            for tool_name in sorted(tool_dict.keys()):
                tool_class = tool_dict[tool_name]
                print(f" * `{tool_name}`: {tool_class.get_tool_description().strip()}")
    
        def is_valid_tool_name(self, tool_name: str) -> bool:
            return tool_name in self._tool_dict
  • Registers the tool instances as MCP tools by name in the FastMCP server, using a wrapper around the Tool's apply method.
    def _set_mcp_tools(self, mcp: FastMCP, openai_tool_compatible: bool = False) -> None:
        """Update the tools in the MCP server"""
        if mcp is not None:
            mcp._tool_manager._tools = {}
            for tool in self._iter_tools():
                mcp_tool = self.make_mcp_tool(tool, openai_tool_compatible=openai_tool_compatible)
                mcp._tool_manager._tools[tool.get_name()] = mcp_tool
            log.info(f"Starting MCP server with {len(mcp._tool_manager._tools)} tools: {list(mcp._tool_manager._tools.keys())}")
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=true and destructiveHint=false, which already convey that this is a safe, non-destructive operation. The description adds context about its role in ensuring task adherence before code modifications, which is useful behavioral insight beyond the annotations. However, it does not detail aspects like potential side effects, performance implications, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded, with three sentences that directly address purpose and usage without unnecessary details. Each sentence adds value, such as the specific trigger conditions and mandatory usage before code changes, making it well-structured and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (low, with 0 parameters), rich annotations (readOnlyHint, destructiveHint), and the presence of an output schema, the description is complete enough. It explains the tool's role in task adherence and when to use it, which aligns with the structured data. However, it could slightly enhance completeness by mentioning what the output schema returns, though this is not strictly necessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has 0 parameters, and schema description coverage is 100%, so there is no need for parameter explanation in the description. The description appropriately does not discuss parameters, which is efficient, but since there are no parameters, a baseline of 4 is applied as it fully compensates for the lack of parameter details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool's purpose as 'Think about the task at hand and whether you are still on track,' which is a clear action but somewhat vague in scope. It does not specify what resources or data it operates on, and it does not distinguish itself from sibling tools like 'think_about_collected_information' or 'think_about_whether_you_are_done,' making it less specific than ideal.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidelines: 'Especially important if the conversation has been going on for a while and there has been a lot of back and forth' and 'This tool should ALWAYS be called before you insert, replace, or delete code.' This gives clear context for when to use it, though it does not explicitly state when not to use it or compare it to alternatives like other 'think' tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oraios/serena'

If you have feedback or need assistance with the MCP directory API, please join our Discord server