mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e39521fa08 | ||
|
|
e9727eb649 | ||
|
|
4e123a4d63 | ||
|
|
f98d969d22 | ||
|
|
74c2ab8588 | ||
|
|
9db1bf8b61 | ||
|
|
9efecdd0e2 |
@@ -34,15 +34,14 @@ from dataclasses import dataclass
|
||||
# (e.g., "packages/core/agent_framework/observability.py")
|
||||
# =============================================================================
|
||||
ENFORCED_TARGETS: set[str] = {
|
||||
# Packages (sorted alphabetically)
|
||||
"packages.anthropic.agent_framework_anthropic",
|
||||
"packages.azure-ai-search.agent_framework_azure_ai_search",
|
||||
# Packages
|
||||
"packages.azure-ai.agent_framework_azure_ai",
|
||||
"packages.core.agent_framework",
|
||||
"packages.core.agent_framework._workflows",
|
||||
"packages.foundry.agent_framework_foundry",
|
||||
"packages.openai.agent_framework_openai",
|
||||
"packages.purview.agent_framework_purview",
|
||||
"packages.anthropic.agent_framework_anthropic",
|
||||
"packages.azure-ai-search.agent_framework_azure_ai_search",
|
||||
"packages.openai.agent_framework_openai",
|
||||
# Individual files (if you want to enforce specific files instead of whole packages)
|
||||
"packages/core/agent_framework/observability.py",
|
||||
# Add more targets here as coverage improves
|
||||
|
||||
@@ -23,7 +23,8 @@ internal sealed class StreamingRunEventStream : IRunEventStream
|
||||
private readonly CancellationTokenSource _runLoopCancellation;
|
||||
private readonly bool _disableRunLoop;
|
||||
private Task? _runLoopTask;
|
||||
private RunStatus _runStatus = RunStatus.NotStarted;
|
||||
private volatile RunStatus _runStatus = RunStatus.NotStarted;
|
||||
|
||||
private int _completionEpoch; // Tracks which completion signal belongs to which consumer iteration
|
||||
|
||||
public StreamingRunEventStream(ISuperStepRunner stepRunner, bool disableRunLoop = false)
|
||||
@@ -127,7 +128,7 @@ internal sealed class StreamingRunEventStream : IRunEventStream
|
||||
|
||||
// Wait for next input from the consumer
|
||||
// Works for both Idle (no work) and PendingRequests (waiting for responses)
|
||||
await this._inputWaiter.WaitForInputAsync(TimeSpan.FromSeconds(1), linkedSource.Token).ConfigureAwait(false);
|
||||
await this._inputWaiter.WaitForInputAsync(linkedSource.Token).ConfigureAwait(false);
|
||||
|
||||
// When signaled, resume running
|
||||
this._runStatus = RunStatus.Running;
|
||||
@@ -209,7 +210,10 @@ internal sealed class StreamingRunEventStream : IRunEventStream
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Get the current epoch - we'll only respond to completion signals from this epoch or later
|
||||
int myEpoch = Volatile.Read(ref this._completionEpoch) + 1;
|
||||
int currentEpoch = Volatile.Read(ref this._completionEpoch);
|
||||
|
||||
bool expectingFreshWork = this._stepRunner.HasUnprocessedMessages || this._runStatus == RunStatus.Running;
|
||||
int myEpoch = expectingFreshWork ? currentEpoch + 1 : currentEpoch;
|
||||
|
||||
// Use custom async enumerable to avoid exceptions on cancellation.
|
||||
NonThrowingChannelReaderAsyncEnumerable<WorkflowEvent> eventStream = new(this._eventChannel.Reader);
|
||||
|
||||
@@ -132,6 +132,53 @@ public class InProcessExecutionTests
|
||||
"both versions should produce the same number of agent events");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This test checks that the logic around waiting for input and halting appropriately works right when the
|
||||
/// workflow runs to halting before the EventStream is watched by the user.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunStreamingAsyncWaitToTakeStreamAsync()
|
||||
{
|
||||
// Arrange: Create a simple agent that responds to messages
|
||||
var agent = new SimpleTestAgent("test-agent");
|
||||
var workflow = AgentWorkflowBuilder.BuildSequential(agent);
|
||||
var inputMessage = new ChatMessage(ChatRole.User, "Hello");
|
||||
|
||||
// Act: Execute using streaming version with TurnToken
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, new List<ChatMessage> { inputMessage });
|
||||
|
||||
// Send TurnToken to actually trigger execution (this is the key step)
|
||||
bool messageSent = await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
messageSent.Should().BeTrue("TurnToken should be accepted");
|
||||
|
||||
while (await run.GetStatusAsync() != RunStatus.Idle)
|
||||
{
|
||||
await Task.Delay(200);
|
||||
}
|
||||
|
||||
// Collect events
|
||||
List<WorkflowEvent> events = [];
|
||||
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
|
||||
{
|
||||
events.Add(evt);
|
||||
}
|
||||
|
||||
// Assert: The workflow should have executed and produced events
|
||||
RunStatus status = await run.GetStatusAsync();
|
||||
status.Should().Be(RunStatus.Idle, "workflow should complete execution");
|
||||
|
||||
events.Should().NotBeEmpty("workflow should produce events during execution");
|
||||
|
||||
// Check that we have agent execution events
|
||||
var agentEvents = events.OfType<AgentResponseUpdateEvent>().ToList();
|
||||
agentEvents.Should().NotBeEmpty("agent should have executed and produced update events");
|
||||
|
||||
// Check that we have output events
|
||||
var outputEvents = events.OfType<WorkflowOutputEvent>().ToList();
|
||||
outputEvents.Should().NotBeEmpty("workflow should produce output events");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple test agent that echoes back the input message.
|
||||
/// </summary>
|
||||
|
||||
@@ -1271,8 +1271,8 @@ class RawAnthropicClient(
|
||||
)
|
||||
)
|
||||
case "input_json_delta":
|
||||
# Skip argument deltas for MCP and server tools — execution is handled server-side.
|
||||
if self._last_call_content_type in ("mcp_tool_use", "server_tool_use"):
|
||||
# Skip argument deltas for MCP tools — execution is handled server-side.
|
||||
if self._last_call_content_type == "mcp_tool_use":
|
||||
pass
|
||||
else:
|
||||
call_id = self._last_call_id_name[0] if self._last_call_id_name else ""
|
||||
|
||||
@@ -1123,53 +1123,6 @@ def test_parse_contents_from_anthropic_input_json_delta_no_duplicate_name(
|
||||
assert result[0].arguments == '"San Francisco"}'
|
||||
|
||||
|
||||
def test_parse_contents_server_tool_use_input_json_delta_ignored(
|
||||
mock_anthropic_client: MagicMock,
|
||||
) -> None:
|
||||
"""Regression test: input_json_delta events are ignored after a server_tool_use block.
|
||||
|
||||
Server-managed tools have their execution handled server-side, so streaming
|
||||
input_json_delta events must not produce Content.from_function_call(name='')
|
||||
entries that would cause Anthropic API 400 errors on subsequent turns.
|
||||
"""
|
||||
client = create_test_anthropic_client(mock_anthropic_client)
|
||||
|
||||
# Simulate a server_tool_use event that sets _last_call_content_type
|
||||
server_tool_content = MagicMock()
|
||||
server_tool_content.type = "server_tool_use"
|
||||
server_tool_content.id = "srvtool_abc"
|
||||
server_tool_content.name = "web_search"
|
||||
server_tool_content.input = {}
|
||||
|
||||
result = client._parse_contents_from_anthropic([server_tool_content])
|
||||
# server_tool_use falls through to function_call (not mcp_tool_use / code_execution)
|
||||
assert len(result) == 1
|
||||
assert result[0].type == "function_call"
|
||||
assert client._last_call_content_type == "server_tool_use" # type: ignore[attr-defined]
|
||||
|
||||
# input_json_delta events after server_tool_use must be silently ignored
|
||||
delta_content = MagicMock()
|
||||
delta_content.type = "input_json_delta"
|
||||
delta_content.partial_json = '{"query": "latest news"}'
|
||||
|
||||
result = client._parse_contents_from_anthropic([delta_content])
|
||||
assert result == [], (
|
||||
"input_json_delta after server_tool_use should produce no content, "
|
||||
"but got: %r" % result
|
||||
)
|
||||
|
||||
# A second delta must also be ignored
|
||||
delta_content_2 = MagicMock()
|
||||
delta_content_2.type = "input_json_delta"
|
||||
delta_content_2.partial_json = '{"extra": true}'
|
||||
|
||||
result = client._parse_contents_from_anthropic([delta_content_2])
|
||||
assert result == [], (
|
||||
"subsequent input_json_delta after server_tool_use should also be ignored, "
|
||||
"but got: %r" % result
|
||||
)
|
||||
|
||||
|
||||
# Stream Processing Tests
|
||||
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ from typing import Annotated
|
||||
from agent_framework import Message, tool
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.observability import enable_instrumentation
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from opentelemetry._logs import set_logger_provider
|
||||
from opentelemetry.metrics import set_meter_provider
|
||||
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
|
||||
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogRecordExporter
|
||||
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogExporter
|
||||
from opentelemetry.sdk.metrics import MeterProvider
|
||||
from opentelemetry.sdk.metrics.export import ConsoleMetricExporter, PeriodicExportingMetricReader
|
||||
from opentelemetry.sdk.resources import Resource
|
||||
@@ -38,7 +37,7 @@ def setup_logging():
|
||||
# Create and set a global logger provider for the application.
|
||||
logger_provider = LoggerProvider(resource=resource)
|
||||
# Log processors are initialized with an exporter which is responsible
|
||||
logger_provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogRecordExporter()))
|
||||
logger_provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogExporter()))
|
||||
# Sets the global default logger provider
|
||||
set_logger_provider(logger_provider)
|
||||
# Create a logging handler to write logging records, in OTLP format, to the exporter.
|
||||
@@ -116,15 +115,11 @@ async def run_chat_client() -> None:
|
||||
2 spans with gen_ai.operation.name=execute_tool
|
||||
|
||||
"""
|
||||
client = FoundryChatClient(credential=AzureCliCredential())
|
||||
client = FoundryChatClient()
|
||||
message = "What's the weather in Amsterdam and in Paris?"
|
||||
print(f"User: {message}")
|
||||
print("Assistant: ", end="")
|
||||
async for chunk in client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
stream=True,
|
||||
options={"tools": [get_weather]},
|
||||
):
|
||||
async for chunk in client.get_response([Message(role="user", text=message)], tools=get_weather, stream=True):
|
||||
if chunk.text:
|
||||
print(chunk.text, end="")
|
||||
print("")
|
||||
|
||||
@@ -7,7 +7,6 @@ from typing import TYPE_CHECKING, Annotated
|
||||
from agent_framework import Message, tool
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.observability import get_tracer
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from opentelemetry.trace import SpanKind
|
||||
from opentelemetry.trace.span import format_trace_id
|
||||
@@ -91,19 +90,12 @@ async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = Fals
|
||||
print(f"User: {message}")
|
||||
if stream:
|
||||
print("Assistant: ", end="")
|
||||
async for chunk in client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
stream=True,
|
||||
options={"tools": [get_weather]},
|
||||
):
|
||||
async for chunk in client.get_response([Message(role="user", text=message)], tools=get_weather, stream=True):
|
||||
if chunk.text:
|
||||
print(chunk.text, end="")
|
||||
print("")
|
||||
else:
|
||||
response = await client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
options={"tools": [get_weather]},
|
||||
)
|
||||
response = await client.get_response([Message(role="user", text=message)], tools=get_weather)
|
||||
print(f"Assistant: {response}")
|
||||
|
||||
|
||||
@@ -111,7 +103,7 @@ async def main() -> None:
|
||||
with get_tracer().start_as_current_span("Zero Code", kind=SpanKind.CLIENT) as current_span:
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
client = FoundryChatClient(credential=AzureCliCredential())
|
||||
client = FoundryChatClient()
|
||||
|
||||
await run_chat_client(client, stream=True)
|
||||
await run_chat_client(client, stream=False)
|
||||
|
||||
@@ -7,7 +7,6 @@ from typing import Annotated
|
||||
from agent_framework import Agent, tool
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.observability import configure_otel_providers, get_tracer
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from opentelemetry.trace import SpanKind
|
||||
from opentelemetry.trace.span import format_trace_id
|
||||
@@ -19,12 +18,6 @@ load_dotenv()
|
||||
"""
|
||||
This sample shows how you can observe an agent in Agent Framework by using the
|
||||
same observability setup function.
|
||||
|
||||
Pre-requisites:
|
||||
- A Foundry project
|
||||
- An observability backend to receive traces and metrics (for example, a local or remote
|
||||
OpenTelemetry Collector, another OTLP-compatible backend, or console exporters enabled
|
||||
via environment variables).
|
||||
"""
|
||||
|
||||
|
||||
@@ -54,7 +47,7 @@ async def main():
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
agent = Agent(
|
||||
client=FoundryChatClient(credential=AzureCliCredential()),
|
||||
client=FoundryChatClient(),
|
||||
tools=get_weather,
|
||||
name="WeatherAgent",
|
||||
instructions="You are a weather assistant.",
|
||||
|
||||
@@ -9,7 +9,6 @@ from typing import TYPE_CHECKING, Annotated, Literal
|
||||
from agent_framework import Message, tool
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.observability import configure_otel_providers, get_tracer
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.trace.span import format_trace_id
|
||||
@@ -25,9 +24,8 @@ This sample shows how you can configure observability of an application via the
|
||||
When you run this sample with an OTLP endpoint or an Application Insights connection string,
|
||||
you should see traces, logs, and metrics in the configured backend.
|
||||
|
||||
Pre-requisites:
|
||||
- A Foundry project
|
||||
- A local OpenTelemetry Collector instance to receive the traces and metrics.
|
||||
If no OTLP endpoint or Application Insights connection string is configured, the sample will
|
||||
output traces, logs, and metrics to the console.
|
||||
"""
|
||||
|
||||
# Load environment variables from .env file
|
||||
@@ -80,18 +78,13 @@ async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = Fals
|
||||
if stream:
|
||||
print("Assistant: ", end="")
|
||||
async for chunk in client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
stream=True,
|
||||
options={"tools": [get_weather]},
|
||||
[Message(role="user", text=message)], tools=get_weather, stream=True
|
||||
):
|
||||
if chunk.text:
|
||||
print(chunk.text, end="")
|
||||
print("")
|
||||
else:
|
||||
response = await client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
options={"tools": [get_weather]},
|
||||
)
|
||||
response = await client.get_response([Message(role="user", text=message)], tools=get_weather)
|
||||
print(f"Assistant: {response}")
|
||||
|
||||
|
||||
@@ -108,7 +101,7 @@ async def run_tool() -> None:
|
||||
with get_tracer().start_as_current_span("Scenario: AI Function", kind=trace.SpanKind.CLIENT):
|
||||
print("Running scenario: AI Function")
|
||||
weather = await get_weather.invoke(location="Amsterdam")
|
||||
print(f"Weather in Amsterdam:\n{weather[-1]}")
|
||||
print(f"Weather in Amsterdam:\n{weather}")
|
||||
|
||||
|
||||
async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "all"):
|
||||
@@ -121,7 +114,7 @@ async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "al
|
||||
with get_tracer().start_as_current_span("Sample Scenarios", kind=trace.SpanKind.CLIENT) as current_span:
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
client = FoundryChatClient(credential=AzureCliCredential())
|
||||
client = FoundryChatClient()
|
||||
|
||||
# Scenarios where telemetry is collected in the SDK, from the most basic to the most complex.
|
||||
if scenario == "tool" or scenario == "all":
|
||||
|
||||
@@ -10,7 +10,6 @@ from typing import TYPE_CHECKING, Annotated, Literal
|
||||
from agent_framework import Message, tool
|
||||
from agent_framework.foundry import FoundryChatClient
|
||||
from agent_framework.observability import configure_otel_providers, get_tracer
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.trace.span import format_trace_id
|
||||
@@ -28,10 +27,6 @@ and allows you to add multiple exporters programmatically.
|
||||
|
||||
For standard OTLP setup, it's recommended to use environment variables (see configure_otel_providers_with_env_var.py).
|
||||
Use this approach when you need custom exporter configuration beyond what environment variables provide.
|
||||
|
||||
Pre-requisites:
|
||||
- A Foundry project
|
||||
- A local OpenTelemetry Collector instance to receive the traces and metrics.
|
||||
"""
|
||||
|
||||
# Load environment variables from .env file
|
||||
@@ -84,18 +79,13 @@ async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = Fals
|
||||
if stream:
|
||||
print("Assistant: ", end="")
|
||||
async for chunk in client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
stream=True,
|
||||
options={"tools": [get_weather]},
|
||||
[Message(role="user", text=message)], stream=True, tools=get_weather
|
||||
):
|
||||
if chunk.text:
|
||||
print(chunk.text, end="")
|
||||
print("")
|
||||
else:
|
||||
response = await client.get_response(
|
||||
[Message(role="user", text=message)],
|
||||
options={"tools": [get_weather]},
|
||||
)
|
||||
response = await client.get_response([Message(role="user", text=message)], tools=get_weather)
|
||||
print(f"Assistant: {response}")
|
||||
|
||||
|
||||
@@ -112,7 +102,7 @@ async def run_tool() -> None:
|
||||
with get_tracer().start_as_current_span("Scenario: AI Function", kind=trace.SpanKind.CLIENT):
|
||||
print("Running scenario: AI Function")
|
||||
weather = await get_weather.invoke(location="Amsterdam")
|
||||
print(f"Weather in Amsterdam:\n{weather[-1]}")
|
||||
print(f"Weather in Amsterdam:\n{weather}")
|
||||
|
||||
|
||||
async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "all"):
|
||||
@@ -163,7 +153,7 @@ async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "al
|
||||
with get_tracer().start_as_current_span("Sample Scenarios", kind=trace.SpanKind.CLIENT) as current_span:
|
||||
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")
|
||||
|
||||
client = FoundryChatClient(credential=AzureCliCredential())
|
||||
client = FoundryChatClient()
|
||||
|
||||
# Scenarios where telemetry is collected in the SDK, from the most basic to the most complex.
|
||||
if scenario == "tool" or scenario == "all":
|
||||
|
||||
@@ -12,9 +12,6 @@ Supported MCP server types:
|
||||
- "http": Remote HTTP server
|
||||
- "sse": Remote SSE (Server-Sent Events) server
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: MCP servers can expose powerful capabilities. Only configure
|
||||
servers you trust. Use permission handlers to control what actions are allowed.
|
||||
"""
|
||||
|
||||
-7
@@ -15,9 +15,6 @@ Available built-in tools:
|
||||
- "Glob": Search for files by pattern
|
||||
- "Grep": Search file contents
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: Only enable permissions that are necessary for your use case.
|
||||
More permissions mean more potential for unintended actions.
|
||||
"""
|
||||
@@ -27,10 +24,6 @@ from typing import Any
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from claude_agent_sdk import PermissionResultAllow, PermissionResultDeny
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def prompt_permission(
|
||||
|
||||
@@ -6,9 +6,6 @@ Claude Agent with Session Management
|
||||
This sample demonstrates session management with ClaudeAgent, showing
|
||||
persistent conversation capabilities. Sessions are automatically persisted
|
||||
by the Claude Code CLI.
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
@@ -17,12 +14,8 @@ from typing import Annotated
|
||||
|
||||
from agent_framework import tool
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from dotenv import load_dotenv
|
||||
from pydantic import Field
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
@tool
|
||||
def get_weather(
|
||||
|
||||
@@ -7,9 +7,6 @@ This sample demonstrates how to enable shell command execution with ClaudeAgent.
|
||||
By providing a permission handler via `can_use_tool`, the agent can execute
|
||||
shell commands to perform tasks like listing files, running scripts, or executing system commands.
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: Only enable shell permissions when you trust the agent's actions.
|
||||
Shell commands have full access to your system within the permissions of the running process.
|
||||
"""
|
||||
@@ -19,10 +16,6 @@ from typing import Any
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from claude_agent_sdk import PermissionResultAllow, PermissionResultDeny
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def prompt_permission(
|
||||
|
||||
@@ -13,18 +13,11 @@ Available built-in tools:
|
||||
- "Edit": Edit existing files
|
||||
- "Glob": Search for files by pattern
|
||||
- "Grep": Search file contents
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
|
||||
@@ -10,9 +10,6 @@ Available web tools:
|
||||
- "WebFetch": Fetch content from URLs
|
||||
- "WebSearch": Search the web
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
|
||||
SECURITY NOTE: Only enable URL permissions when you trust the agent's actions.
|
||||
URL fetching allows the agent to access any URL accessible from your network.
|
||||
"""
|
||||
@@ -20,10 +17,6 @@ URL fetching allows the agent to access any URL accessible from your network.
|
||||
import asyncio
|
||||
|
||||
from agent_framework.anthropic import ClaudeAgent
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
|
||||
@@ -21,10 +21,6 @@ This sample demonstrates using Anthropic with:
|
||||
You can also set additonal_chat_options with "additional_beta_flags" per request.
|
||||
- Creating an agent with the Code Interpreter tool and a Skill.
|
||||
- Catching and downloading generated files from the agent.
|
||||
|
||||
Environment variables:
|
||||
- ANTHROPIC_API_KEY: Your Anthropic API key
|
||||
- ANTHROPIC_CHAT_MODEL_ID: The Anthropic model to use, such as "claude-sonnet-4-5-20250929"
|
||||
"""
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user