Agent Self-Management Tool: Dynamic Context Loading
This tool allows an agent to dynamically attach/detach their own tools and memory blocks at runtime.
Implementation
def manage_context(
action: str,
resource_type: str,
resource_identifier: str
) -> str:
"""
Dynamically manage my own tools and memory blocks.
Args:
action: Either "attach" or "detach"
resource_type: Either "tool" or "block"
resource_identifier: Tool/block name or ID
Returns:
Status message
"""
import os
# client is pre-injected on Cloud
agent_id = os.getenv("LETTA_AGENT_ID")
if not agent_id:
return "Error: Agent ID not available"
try:
# Find resource by name or use ID directly
if resource_type == "tool":
if not resource_identifier.startswith("tool-"):
# Find by name
tools = client.tools.list()
tool = next((t for t in tools.items if t.name == resource_identifier), None)
if not tool:
return f"Tool '{resource_identifier}' not found"
resource_id = tool.id
else:
resource_id = resource_identifier
# Attach or detach
if action == "attach":
client.agents.tools.attach(agent_id, resource_id)
return f"✓ Attached tool: {resource_identifier}"
elif action == "detach":
client.agents.tools.detach(agent_id, resource_id)
return f"✓ Detached tool: {resource_identifier}"
elif resource_type == "block":
if not resource_identifier.startswith("block-"):
# Find by label
blocks = client.blocks.list()
block = next((b for b in blocks.items if b.label == resource_identifier), None)
if not block:
return f"Block '{resource_identifier}' not found"
resource_id = block.id
else:
resource_id = resource_identifier
# Attach or detach
if action == "attach":
client.agents.blocks.attach(agent_id, resource_id)
return f"✓ Attached block: {resource_identifier}"
elif action == "detach":
client.agents.blocks.detach(agent_id, resource_id)
return f"✓ Detached block: {resource_identifier}"
else:
return f"Invalid resource_type: {resource_type}. Use 'tool' or 'block'"
except Exception as e:
return f"Error managing context: {str(e)}"
Key Implementation Details
clientvariable: Pre-injected on Letta Cloud tools, no initialization neededLETTA_AGENT_ID: Environment variable containing the agent’s own ID- Flexible lookup: Accepts either names (“web_search”) or IDs (“tool-abc123…”)
- Immediate effect: Changes apply instantly to the agent
Usage Examples
From the agent’s perspective:
# Attach a tool when needed
manage_context("attach", "tool", "web_search")
# Attach a memory block
manage_context("attach", "block", "project_context")
# Detach when done
manage_context("detach", "tool", "web_search")
# Detach a memory block
manage_context("detach", "block", "project_context")
Use Cases
Context optimization: Agent loads specific tools only when needed (coding tools for coding tasks, research tools for research)
Memory management: Agent loads relevant memory blocks based on conversation phase (onboarding blocks, active project blocks, debugging blocks)
Resource efficiency: Reduces context window usage by only loading what’s currently needed
Caveats
- Agent needs to know available tool/block names (consider adding a “list” action for discovery)
- Changes persist across conversations
- Consider adding guardrails to prevent detaching critical resources
- Works on Letta Cloud (relies on pre-injected
clientvariable andLETTA_AGENT_IDenv var)
Related Documentation
Requested by @fimeg for the Ani agent use case.