Skip to content

Commit 9c3d58a

Browse files
ZhiXiao-Linclaude
andcommitted
fix: remove all tracing spans from async execution paths
tracing 0.1.41+ made Span !Send via PhantomNotSend. Any Span local variable that lives across an .await boundary makes the entire async future !Send, breaking tokio::spawn and JoinSet::spawn. Remove all info_span!/Instrument usage from execute_loop and execute_with_session. Replace with tracing::info! events that fire immediately without holding state across await points. All existing tracing::info!/warn! log events at tool start/end, turn start/end, and LLM completion are preserved — the removed spans were redundant with these events. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 46d0d2e commit 9c3d58a

1 file changed

Lines changed: 13 additions & 47 deletions

File tree

core/src/agent.rs

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use serde_json::Value;
3030
use std::sync::Arc;
3131
use std::time::Duration;
3232
use tokio::sync::{mpsc, RwLock};
33-
use tracing::Instrument;
3433

3534
/// Maximum number of tool execution rounds before stopping
3635
const MAX_TOOL_ROUNDS: usize = 50;
@@ -940,18 +939,11 @@ impl AgentLoop {
940939
.ok();
941940
}
942941

943-
let context_results = {
944-
let context_span = tracing::info_span!(
945-
"a3s.agent.context_resolve",
946-
a3s.context.providers = self.config.context_providers.len() as i64,
947-
a3s.context.items = tracing::field::Empty,
948-
a3s.context.tokens = tracing::field::Empty,
949-
);
950-
951-
self.resolve_context(prompt, session_id)
952-
.instrument(context_span)
953-
.await
954-
};
942+
tracing::info!(
943+
a3s.context.providers = self.config.context_providers.len() as i64,
944+
"Context resolution started"
945+
);
946+
let context_results = self.resolve_context(prompt, session_id).await;
955947

956948
// Send context resolved event
957949
if let Some(tx) = &event_tx {
@@ -983,13 +975,6 @@ impl AgentLoop {
983975
loop {
984976
turn += 1;
985977

986-
let turn_span = tracing::info_span!(
987-
"a3s.agent.turn",
988-
a3s.agent.turn_number = turn as i64,
989-
a3s.llm.total_tokens = tracing::field::Empty,
990-
);
991-
let _turn_guard = turn_span.enter();
992-
993978
if turn > self.config.max_tool_rounds {
994979
let error = format!("Max tool rounds ({}) exceeded", self.config.max_tool_rounds);
995980
if let Some(tx) = &event_tx {
@@ -1014,15 +999,10 @@ impl AgentLoop {
1014999
);
10151000

10161001
// Call LLM - use streaming if we have an event channel
1017-
let llm_span = tracing::info_span!(
1018-
"a3s.llm.completion",
1002+
tracing::info!(
10191003
a3s.llm.streaming = event_tx.is_some(),
1020-
a3s.llm.prompt_tokens = tracing::field::Empty,
1021-
a3s.llm.completion_tokens = tracing::field::Empty,
1022-
a3s.llm.total_tokens = tracing::field::Empty,
1023-
a3s.llm.stop_reason = tracing::field::Empty,
1004+
"LLM completion started"
10241005
);
1025-
let _llm_guard = llm_span.enter();
10261006

10271007
// Fire GenerateStart hook
10281008
self.fire_generate_start(session_id.unwrap_or(""), prompt, &augmented_system)
@@ -1103,10 +1083,12 @@ impl AgentLoop {
11031083
response.usage.total_tokens,
11041084
response.stop_reason.as_deref(),
11051085
);
1106-
drop(_llm_guard);
1107-
1108-
// Record total tokens on the turn span
1109-
turn_span.record("a3s.llm.total_tokens", response.usage.total_tokens as i64);
1086+
// Log turn token usage
1087+
tracing::info!(
1088+
turn = turn,
1089+
a3s.llm.total_tokens = response.usage.total_tokens,
1090+
"Turn token usage"
1091+
);
11101092

11111093
// Add assistant message to history
11121094
messages.push(response.message.clone());
@@ -1188,17 +1170,6 @@ impl AgentLoop {
11881170
for tool_call in sequential_tools {
11891171
tool_calls_count += 1;
11901172

1191-
let tool_span = tracing::info_span!(
1192-
"a3s.tool.execute",
1193-
a3s.tool.name = tool_call.name.as_str(),
1194-
a3s.tool.id = tool_call.id.as_str(),
1195-
a3s.tool.exit_code = tracing::field::Empty,
1196-
a3s.tool.success = tracing::field::Empty,
1197-
a3s.tool.duration_ms = tracing::field::Empty,
1198-
a3s.tool.permission = tracing::field::Empty,
1199-
);
1200-
let _tool_guard = tool_span.enter();
1201-
12021173
let tool_start = std::time::Instant::now();
12031174

12041175
tracing::info!(
@@ -1327,7 +1298,6 @@ impl AgentLoop {
13271298
permission = "deny",
13281299
"Tool permission denied"
13291300
);
1330-
tool_span.record("a3s.tool.permission", "deny");
13311301
// Tool execution denied by permission policy
13321302
let denial_msg = format!(
13331303
"Permission denied: Tool '{}' is blocked by permission policy.",
@@ -1354,8 +1324,6 @@ impl AgentLoop {
13541324
permission = "allow",
13551325
"Tool permission: allow"
13561326
);
1357-
tool_span.record("a3s.tool.permission", "allow");
1358-
13591327
// Permission explicitly allows — execute directly, no HITL
13601328
let stream_ctx =
13611329
self.streaming_tool_context(&event_tx, &tool_call.id, &tool_call.name);
@@ -1375,8 +1343,6 @@ impl AgentLoop {
13751343
permission = "ask",
13761344
"Tool permission: ask"
13771345
);
1378-
tool_span.record("a3s.tool.permission", "ask");
1379-
13801346
// Permission says Ask — delegate to HITL confirmation manager
13811347
if let Some(cm) = &self.config.confirmation_manager {
13821348
// Check YOLO lanes: if the tool's lane is in YOLO mode, skip confirmation

0 commit comments

Comments
 (0)