Verifies that every way of creating a tool acceptsDocumentation Index
Fetch the complete documentation index at: https://docs.vectorshift.ai/llms.txt
Use this file to discover all available pages before exploring further.
approval_config and
that the value flows through to the serialized save payload the backend
consumes.
Paths exercised:
1. Direct class instantiation - ExaAiTool(...)
2. AgentTools namespace - AgentTools.google_search(...)
3. Fluent adder on an agent - agent.add_tool.wikipedia(...)
VECTORSHIFT_API_KEY is set,
the example also saves the agent and deletes it to confirm the backend
accepts the payload.
from __future__ import annotations
import os
from vectorshift.agent import Agent, AgentTools, AgentType, LlmInfo, MemoryConfig
from vectorshift.agent.tool import ToolApprovalConfig, ToolInput, ToolInputType
from vectorshift.agent.tools import ExaAiTool
EXPECTED = {
"exa_ai": ToolApprovalConfig.REQUIRES_APPROVAL,
"google_search": ToolApprovalConfig.LET_AGENT_DECIDE,
"wikipedia": ToolApprovalConfig.AUTO_RUN,
}
def build_agent() -> Agent:
search = ExaAiTool(
query=ToolInput(type=ToolInputType.DYNAMIC, description="Search query"),
approval_config=EXPECTED["exa_ai"],
)
google = AgentTools.google_search(
query=ToolInput(type=ToolInputType.DYNAMIC, description="Search query"),
num_results=5,
approval_config=EXPECTED["google_search"],
)
agent = Agent(
id="approval-demo",
name="Approval demo assistant",
agent_type=AgentType.CONVERSATIONAL,
llm_info=LlmInfo(provider="openai", model_id="gpt-4o"),
tools=[search, google],
instructions="Use web search when the user asks about current events.",
memory_config=MemoryConfig(enable_session_memory=True),
)
agent.add_tool.wikipedia(
query=ToolInput(type=ToolInputType.DYNAMIC, description="Topic to look up"),
approval_config=EXPECTED["wikipedia"],
)
return agent
def main() -> None:
agent = build_agent()
print("In-memory tool values:")
by_type = {t.tool_type: t for t in agent.tools}
for tool_type, expected in EXPECTED.items():
actual = by_type[tool_type].approval_config
assert actual == expected, f"{tool_type}: expected {expected}, got {actual}"
print(f" [OK] {tool_type:20s} approval_config = {actual}")
# Reach into _serialize_tools to show exactly what save() puts on the wire —
# the backend parser expects approval_config at the top of each tool dict,
# not nested under 'value' or 'inputs'.
print("\nSerialized payload (what save() sends to the backend):")
serialized = Agent._serialize_tools(agent.tools)
for entry in serialized.values():
assert "approval_config" not in entry["value"]
assert "approval_config" not in entry["value"]["inputs"]
print(
f" {entry['value']['node_type']:20s}"
f" approval_config = {entry['approval_config']!r}"
)
if not os.environ.get("VECTORSHIFT_API_KEY"):
print("\nVECTORSHIFT_API_KEY not set - skipping backend round-trip.")
return
print("\nSaving agent to verify the backend accepts the payload...")
agent.save()
print(f" Saved agent id={agent.id}")
agent.delete()
print(" Deleted agent.")
if __name__ == "__main__":
main()
Source:
examples/agents/16_tool_approval_config.py in the SDK repo.