Skip to content

Conversation

@saksharthakkar
Copy link
Contributor

@saksharthakkar saksharthakkar commented Dec 31, 2025

Summary

Add metadata to tools and guardrails for observability span detection.

Changes:

  • escalation_tool.py: Add metadata (tool_type, display_name, channel_type, assignee)
  • process_tool.py: Add metadata (tool_type, display_name, folder_path)
  • guardrail_nodes.py: Attach __metadata__ attribute (guardrail_name, guardrail_scope, guardrail_stage, tool_name)

Metadata usage

Core (span detection):

  • tool_type, display_name → identify interruptible tool type and span name

Span attributes (temporal parity):

  • channel_type, assignee, folder_path → additional span attributes

Why tool_name in guardrail metadata?
For TOOL scope guardrails, correlates guardrail span with parent tool span for proper hierarchy.

Why __metadata__ for nodes but metadata for tools?
StructuredTool has built-in metadata param. Guardrail nodes are plain async functions—need manual __metadata__ attribute that callbacks read via getattr().

Why

Metadata is the cleanest approach: it's the standard LangChain pattern, flows automatically to callbacks, and requires no parsing.

tool_type is explicit because Python SDK tools share the same StructuredTool base class—unlike temporal's polymorphic GetToolType(), we can't derive type from class hierarchy.

Removes name-based hacks in uipath-agents-python callback:

# TODO: Remove when uipath-langchain passes metadata
tool_type = "escalation" if tool_name.startswith("escalate_") else None

saksharthakkar and others added 7 commits December 30, 2025 16:38
Add metadata to tools and guardrails for observability span detection.

Changes:
- escalation_tool.py: Add metadata (tool_type, display_name, channel_type, assignee)
- process_tool.py: Add metadata (tool_type, display_name, folder_path)
- guardrail_nodes.py: Wrap in RunnableCallable with metadata

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
RunnableCallable passes metadata as kwargs which breaks node invocation.
Use __metadata__ attribute on function instead, which callbacks can read.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Can be inferred from guardrail_name presence.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add test_process_tool.py for process tool metadata
- Add test_escalation_tool.py for escalation tool metadata
- Add TestGuardrailNodeMetadata to guardrail node tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Use getattr() for __metadata__ access (avoids type:ignore)
- Add assert metadata is not None before indexing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@saksharthakkar saksharthakkar marked this pull request as ready for review December 31, 2025 01:49
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@saksharthakkar saksharthakkar merged commit 6589850 into main Jan 2, 2026
60 of 61 checks passed
@saksharthakkar saksharthakkar deleted the feat/observability-metadata branch January 2, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants