Skip to content

feat(chat): render tool-call failure explanations in View-processing timeline (#4254, frontend)#4413

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:feat/GH-4254-tool-status-failure-recovery
Jul 3, 2026
Merged

feat(chat): render tool-call failure explanations in View-processing timeline (#4254, frontend)#4413
senamakel merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:feat/GH-4254-tool-status-failure-recovery

Conversation

@M3gA-Mind

@M3gA-Mind M3gA-Mind commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

The chat "View processing" timeline render for tool-call failures — the frontend half of #4254. It reads the structured failure (class + plain-language cause + next action) off the tool_result socket event and shows a "why / what to do next" pair instead of a raw error string.

Scope change (was full-stack → now frontend-only)

This PR originally shipped the backend classifier too, but that conflicted with #4399 (the TinyAgents harness migration) and has been reworked separately in #4445 (tool_status module + ToolOutcomeCaptureMiddleware + WebChannelEvent.failure). This PR is now reduced to just the frontend consumer, rebased cleanly onto current main.

What's here (21 files)

  • Chat render: ProcessingTranscriptView (+test), ChatRuntimeProvider, chatService, chatRuntimeSlice (+toolFailure test), turnState.
  • i18n: conversations.toolFailure.* keys across all 14 locales (real translations), 3-way unioned onto current main so no existing translations are reverted.

Validation

  • pnpm typecheck clean.
  • pnpm i18n:check — 0 missing / 0 extra across all locales (parity holds).
  • 13 frontend tests pass (chatRuntimeSlice.toolFailure + ProcessingTranscriptView).

Merge order

Stacked on #4445 — merge that first; it emits the WebChannelEvent.failure this PR renders. (Both currently also inherit the pre-existing main "Rust E2E (mock backend)" red, which is unrelated to either PR.)

@M3gA-Mind M3gA-Mind requested a review from a team July 2, 2026 11:49
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds tool-failure classification and transport plumbing in Rust, carries the failure payload into the chat runtime, and renders localized “why” and “next” explanations in the conversation UI across all supported locales.

Changes

Tool failure classification feature

Layer / File(s) Summary
Tool status classification types and logic
src/openhuman/tool_status/mod.rs, src/openhuman/tool_status/types.rs, src/openhuman/tool_status/ops.rs, src/openhuman/mod.rs
Defines ToolLifecycleState, ToolFailureClass, FailureCategory, and ClassifiedFailure, plus classify/describe helpers and tests.
Tool executor produces classified failures
src/openhuman/agent/dispatcher.rs, src/openhuman/agent/harness/session/agent_tool_exec.rs, src/openhuman/agent/harness/engine/progress.rs, src/openhuman/agent/progress.rs, and related tests
Adds failure fields to tool result/progress types, classifies blocked/error/timeout/unknown outcomes, and forwards failure data through executor and progress reporting.
Domain event and web transport propagation
src/core/event_bus/events.rs, src/core/socketio.rs, src/openhuman/channels/providers/web/progress_bridge.rs, src/openhuman/runtime_node/ops.rs, src/core/event_bus/events_tests.rs
Extends domain/web event payloads with optional failure JSON and serializes it through the progress bridge.
Frontend chat runtime parses failure payload
app/src/services/chatService.ts, app/src/store/chatRuntimeSlice.ts, app/src/store/chatRuntimeSlice.toolFailure.test.ts, app/src/types/turnState.ts, app/src/providers/ChatRuntimeProvider.tsx
Adds failure types and parsing, extends persisted timeline data, and attaches or clears failure info on incoming tool results.
Localized failure UI rendering and tests
app/src/pages/conversations/components/ProcessingTranscriptView.tsx, ProcessingTranscriptView.test.tsx, app/src/lib/i18n/*.ts
Renders localized failure explanations in the transcript view and adds translations for the new keys across all locale files.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Sequence Diagram(s)

sequenceDiagram
  participant AgentToolExec
  participant tool_status
  participant progress_bridge
  participant ChatRuntimeProvider
  participant chatRuntimeSlice
  participant ProcessingTranscriptView

  AgentToolExec->>tool_status: classify(error_text, timed_out)
  tool_status-->>AgentToolExec: ClassifiedFailure
  AgentToolExec->>progress_bridge: ToolExecutionCompleted{failure}
  progress_bridge->>ChatRuntimeProvider: tool_result{failure JSON}
  ChatRuntimeProvider->>chatRuntimeSlice: parseToolFailure(raw)
  chatRuntimeSlice-->>ProcessingTranscriptView: ToolTimelineEntry{failure}
  ProcessingTranscriptView->>ProcessingTranscriptView: render why/next
Loading

Suggested labels: feature, rust-core, agent

Suggested reviewers: graycyrus

Poem

A rabbit hopped through code so bright,
And taught each failure how to light.
With “why” and “next” in every tongue,
The tool-fail tale is now well sung. 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main frontend change: rendering tool-call failure explanations in the View-processing timeline.

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e5d2af2821

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

subagent: entry.subagent ? subagentActivityFromPersisted(entry.subagent) : undefined,
// Carry a persisted failure explanation across the round-trip (#4254). The
// shared parser tolerates both camelCase (persisted) and snake_case (wire).
failure: parseToolFailure(entry.failure),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Persist tool failures in turn-state snapshots

When a failed tool row is rehydrated from openhuman.threads_turn_state_get after a reload or thread switch, this parser never receives a value because the Rust snapshot type still has no failure field on src/openhuman/threads/turn_state/types.rs::ToolTimelineEntry, and the mirror handles AgentProgress::ToolCallCompleted { call_id, success, .. } without storing the new failure payload. The live socket path shows the explanation, but settled/reloaded turns drop the new “why / what to do next” text; add the failure field to the Rust turn-state row and set/clear it in the mirror on completion.

Useful? React with 👍 / 👎.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Fixed the two red lanes:

Rust Quality (fmt, clippy) — the failure was cargo fmt --check. Ran cargo fmt: reflowed a few over-long lines in agent_tool_exec.rs, channels/providers/web/progress_bridge.rs, and the tool_status/ops.rs test asserts. cargo clippy -p openhuman already compiled clean (exit 0); no code changes needed there.

Frontend Checks — the failure was format:check (Prettier flagged 7 files). Ran prettier --write on the i18n locale additions (ar, fr, hi, id, ru, zh-CN) and ProcessingTranscriptView.tsx.

Verified locally, all green: cargo fmt --all -- --check, cargo clippy -p openhuman, prettier --check ., tsc --noEmit, eslint (0 errors), pnpm i18n:check (0 missing/extra across all locales), and the new Vitest specs (ProcessingTranscriptView.test.tsx, chatRuntimeSlice.toolFailure.test.ts) pass 13/13. No behavior change — formatting only.

@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. labels Jul 2, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/openhuman/channels/providers/web/progress_bridge.rs (1)

411-416: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate failure-serialization one-liner.

The failure.as_ref().and_then(|f| serde_json::to_value(f).ok()) pattern is duplicated verbatim in agent_tool_exec.rs. Consider extracting a small shared helper (e.g. ClassifiedFailure::to_json(&self) -> serde_json::Value or a free function) to avoid drift between the two call sites, and optionally log a warning on serialization failure instead of silently dropping it.

♻️ Example consolidation
-let failure_json = failure.as_ref().and_then(|f| serde_json::to_value(f).ok());
+let failure_json = failure.as_ref().and_then(|f| {
+    serde_json::to_value(f)
+        .map_err(|e| log::warn!("failed to serialize ClassifiedFailure: {e}"))
+        .ok()
+});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/channels/providers/web/progress_bridge.rs` around lines 411 -
416, The failure-to-JSON conversion logic is duplicated in `progress_bridge` and
`agent_tool_exec`, so extract a shared helper on `ClassifiedFailure` or a small
free function to centralize `failure.as_ref().and_then(|f|
serde_json::to_value(f).ok())`. Update both call sites to use that helper so the
serialization behavior stays consistent and doesn’t drift. If serialization
still fails, consider logging a warning at the helper boundary instead of
silently discarding the error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/lib/i18n/zh-CN.ts`:
- Around line 20-21: The blocked-by-policy message uses a mismatched settings
label in the zh-CN i18n entries, so update the
`conversations.toolFailure.blockedByPolicy.next` translation to reference the
existing `settings.agentAccess.title` wording used elsewhere in this file. Keep
the rest of the sentence intact and replace `代理访问` with the same translated
label users will see in the UI (`智能体系统访问`) so the navigation hint matches the
actual settings title.

---

Nitpick comments:
In `@src/openhuman/channels/providers/web/progress_bridge.rs`:
- Around line 411-416: The failure-to-JSON conversion logic is duplicated in
`progress_bridge` and `agent_tool_exec`, so extract a shared helper on
`ClassifiedFailure` or a small free function to centralize
`failure.as_ref().and_then(|f| serde_json::to_value(f).ok())`. Update both call
sites to use that helper so the serialization behavior stays consistent and
doesn’t drift. If serialization still fails, consider logging a warning at the
helper boundary instead of silently discarding the error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e18ca717-4eb6-4a28-a432-c0c443a4804d

📥 Commits

Reviewing files that changed from the base of the PR and between f979bfa and a1422e0.

📒 Files selected for processing (41)
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/pages/conversations/components/ProcessingTranscriptView.test.tsx
  • app/src/pages/conversations/components/ProcessingTranscriptView.tsx
  • app/src/providers/ChatRuntimeProvider.tsx
  • app/src/services/chatService.ts
  • app/src/store/chatRuntimeSlice.toolFailure.test.ts
  • app/src/store/chatRuntimeSlice.ts
  • app/src/types/turnState.ts
  • src/bin/harness_subagent_audit.rs
  • src/core/event_bus/events.rs
  • src/core/event_bus/events_tests.rs
  • src/core/socketio.rs
  • src/openhuman/agent/dispatcher.rs
  • src/openhuman/agent/dispatcher_tests.rs
  • src/openhuman/agent/harness/engine/progress.rs
  • src/openhuman/agent/harness/session/agent_tool_exec.rs
  • src/openhuman/agent/harness/tool_result_artifacts/mod.rs
  • src/openhuman/agent/progress.rs
  • src/openhuman/agent/progress_tracing/tests.rs
  • src/openhuman/agent/tests.rs
  • src/openhuman/channels/providers/web/progress_bridge.rs
  • src/openhuman/mod.rs
  • src/openhuman/runtime_node/ops.rs
  • src/openhuman/threads/turn_state/mirror_tests.rs
  • src/openhuman/tinyagents/observability.rs
  • src/openhuman/tool_status/mod.rs
  • src/openhuman/tool_status/ops.rs
  • src/openhuman/tool_status/types.rs

Comment thread app/src/lib/i18n/zh-CN.ts
Comment on lines +20 to +21
'conversations.toolFailure.blockedByPolicy.cause': '此操作已被你的安全设置阻止。',
'conversations.toolFailure.blockedByPolicy.next': '如果希望执行,请在“设置 → 代理访问”中允许它。',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the existing settings label here.

settings.agentAccess.title is translated elsewhere in this file as 智能体系统访问, so 代理访问 will send users to a label they cannot match in the UI.

♻️ Proposed fix
-  'conversations.toolFailure.blockedByPolicy.next': '如果希望执行,请在“设置 → 代理访问”中允许它。',
+  'conversations.toolFailure.blockedByPolicy.next': '如果希望执行,请在“设置 → 智能体系统访问”中允许它。',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'conversations.toolFailure.blockedByPolicy.cause': '此操作已被你的安全设置阻止。',
'conversations.toolFailure.blockedByPolicy.next': '如果希望执行,请在“设置 → 代理访问”中允许它。',
'conversations.toolFailure.blockedByPolicy.cause': '此操作已被你的安全设置阻止。',
'conversations.toolFailure.blockedByPolicy.next': '如果希望执行,请在“设置 → 智能体系统访问”中允许它。',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/lib/i18n/zh-CN.ts` around lines 20 - 21, The blocked-by-policy
message uses a mismatched settings label in the zh-CN i18n entries, so update
the `conversations.toolFailure.blockedByPolicy.next` translation to reference
the existing `settings.agentAccess.title` wording used elsewhere in this file.
Keep the rest of the sentence intact and replace `代理访问` with the same translated
label users will see in the UI (`智能体系统访问`) so the navigation hint matches the
actual settings title.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Follow-up: the Rust Quality (clippy) lane was still red after the fmt push — a real compile error the PR introduced, not covered by my formatting commit:

error[E0063]: missing field failurein initializer ofcore::socketio::WebChannelEvent``

The #4254 change added the required failure: Option<serde_json::Value> field to WebChannelEvent, but four struct literals were never updated:

  • channels/providers/presentation.rschat_done, segmented-message, and reaction events (×3)
  • channels/proactive.rsproactive_message event

These are non-tool-failure channel events, so the correct value is failure: None (matching the usage: None etc. siblings). Fixed all four.

Verified locally green: cargo clippy -p openhuman (exit 0) and cargo fmt --all -- --check (exit 0). Test-target literals were unaffected (they use ..Default::default() / return received events).

(My earlier local clippy pass was masked by stale incremental build artifacts; caught it from the CI log and reproduced with a clean rebuild.)

@coderabbitai coderabbitai Bot added the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label Jul 2, 2026
@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Also checked the two remaining PR Submission Checklist boxes — both were already written as honest N/A (coverage-matrix: additive UI/observability, no feature-ID row; manual-smoke: doesn't touch release-cut surfaces) but left unticked, which the parser hard-fails on. Ticked them as-is; no content faked.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Heads-up: this PR can't be cleanly rebased onto post-#4399 main. Besides the i18n keys (which rebase fine), it modifies src/openhuman/agent/harness/session/agent_tool_exec.rs, which #4399 deleted when it migrated the tool-execution path onto the tinyagents crate — so it's a modify/delete conflict, not a content one. The tool-exec-failure-explanation portion needs reworking against the current harness (re-expressed as middleware / at the new tool-exec seam), same as #4388/#4390. The i18n half is unaffected.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Split by #4399 (harness migration). This PR's backend — the tool-failure classification hook — patched session/agent_tool_exec.rs, which #4399 deleted (the tool loop moved onto the tinyagents crate). That backend is reworked in #4445: it re-homes the classifier onto the adapter seam (ToolOutcomeCaptureMiddleware + a call_id → (success, failure) side-channel read by the event bridge), and fixes a latent bug it uncovered — the tinyagents path hardcoded success: true, so failed tools never surfaced. 16 tool_status unit tests pass.

The frontend + i18n half of this PR does NOT conflict with #4399 and rebases cleanly onto current main. I left it out of #4445 because pulling the whole locale files would revert unrelated translation drift that landed on main since this branch. Recommended: rebase this PR down to just its frontend/i18n commits (they consume WebChannelEvent.failure, which #4445 now emits), and merge alongside #4445 (both stacked on the build-fix #4442).

M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Jul 3, 2026
…ent (tinyhumansai#4254, backend)

Rework of tinyhumansai#4413's backend onto post-tinyhumansai#4399 code. tinyhumansai#4399 deleted the original
classification hook (session/agent_tool_exec.rs) and the ProgressReporter
trait; the tool loop now runs on the tinyagents crate, so the hook is
re-homed on the adapter seam.

- New `src/openhuman/tool_status/` module: `classify(error_text, timed_out)`
  and `describe(class)` map a tool outcome to a `ClassifiedFailure`
  (class + category + plain-language cause + next action). Pure, unit-tested
  (16 tests: all classes, timeout/unknown/precedence, category mapping,
  recoverability).
- `AgentProgress::ToolCallCompleted` + `WebChannelEvent` gain a `failure`
  field carrying that classification to the chat "View processing" timeline.
- Core hook + latent-bug fix: the crate's `AgentEvent::ToolCompleted` carries
  only call_id + tool_name, so the bridge previously hardcoded `success: true`
  (a failed tool never surfaced). `ToolOutcomeCaptureMiddleware::after_tool`
  now classifies each result and writes a `call_id → (success, failure)`
  side-channel (mirroring the existing `ToolNameMap`); the bridge reads it to
  emit real `success` + `failure`. Absent entry falls back to `(true, None)`.
- `progress_bridge` serializes `failure` onto the `tool_result` socket event
  and the run ledger.

Backend only. The frontend consumer (chat timeline "why / next" render) and
i18n keys are a companion — they rebase cleanly onto current `main` from
tinyhumansai#4413 (only the Rust hook conflicted with tinyhumansai#4399), so they are not re-included
here to avoid reverting unrelated locale drift.

NOTE: the middleware-before-event ordering that populates the side-channel is
crate-internal; the fallback keeps behavior no worse than before if the event
is ever projected first. Needs runtime validation once tinyhumansai#4442 lands (drive a
deliberately-failing tool and confirm `success:false` + `failure` on the wire).
…ed in tinyhumansai#4445

tinyhumansai#4413 originally shipped both the tool-failure classification backend and the
chat "View processing" render. The backend conflicted with tinyhumansai#4399 (harness
migration) and has been reworked separately in tinyhumansai#4445 (tool_status module +
ToolOutcomeCaptureMiddleware + WebChannelEvent.failure). This reduces tinyhumansai#4413 to
just the frontend that consumes tinyhumansai#4445's `failure` field off the tool_result
socket event, rebased cleanly onto current main.

Kept (21 files):
- chat timeline render: ProcessingTranscriptView (+test), ChatRuntimeProvider,
  chatService, chatRuntimeSlice (+toolFailure test), turnState.
- i18n: conversations.toolFailure.* keys across all 14 locales (3-way unioned
  onto current main so no existing translations are reverted).

Dropped (now owned by tinyhumansai#4445): tool_status/, agent progress/observability,
middleware, event_bus, socketio failure plumbing, and the deleted-file conflict
on agent_tool_exec.rs.

Verified: pnpm typecheck clean, i18n:check parity 0 missing/0 extra, 13 frontend
tests pass (chatRuntimeSlice.toolFailure + ProcessingTranscriptView).
Stacked on tinyhumansai#4445 (merge that first — it emits the field this renders).
@M3gA-Mind M3gA-Mind force-pushed the feat/GH-4254-tool-status-failure-recovery branch from d2ef245 to 8e807f5 Compare July 3, 2026 15:56
@M3gA-Mind M3gA-Mind changed the title Human-readable tool-call failure explanations feat(chat): render tool-call failure explanations in View-processing timeline (#4254, frontend) Jul 3, 2026
@senamakel senamakel merged commit 28331c9 into tinyhumansai:main Jul 3, 2026
17 of 19 checks passed
senamakel pushed a commit that referenced this pull request Jul 3, 2026
senamakel added a commit to senamakel/openhuman that referenced this pull request Jul 4, 2026
… failure in snapshot (tinyhumansai#4459)

Repairs tinyhumansai#4413 tool-failure classification.

A/B/E: the classifier now short-circuits POLICY_BLOCKED_MARKER and
POLICY_DENIED_MARKER *before* the `timed out` sniff, so a user deny →
`Denied` and an approval-TTL expiry → `ApprovalExpired` (both
`FailureCategory::UserDeclined`, non-retryable, honest copy) instead of a
recoverable Unknown "try again" or a Timeout "will retry". Middleware now
sniffs both `error` and `content`, and the dead `"policy denied"` needle is
removed.

C: `ToolTimelineEntry` gains `failure: Option<PersistedToolFailure>`
(camelCase, matching the TS `PersistedToolFailure` contract) threaded through
`mirror.rs`, so a failed tool's explanation survives thread switch / restart.

D: `SubagentToolCallCompleted` gains a `failure` field populated from the
already-computed classification (observability.rs) and forwarded on the web
event + persisted `SubagentToolCall`, so failed sub-agent rows carry an
explanation.

Frontend: TS types (`PersistedSubagentToolCall.failure`,
`SubagentToolCallEntry.failure`, slice mapping), the localized-failure-class
set gains `denied`/`approvalExpired`, and i18n keys land in en.ts + all
locales.

Tests deferred to the final pass.

Claude-Session: https://claude.ai/code/session_019j5TLsRLHsM3kqAYFyH4hR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants