Skip to content

Add native agentic runner (kind: "agent") on pi agent-core + ai#18

Merged
inhaq merged 8 commits into
mainfrom
pi-native-agent-runner
Jun 15, 2026
Merged

Add native agentic runner (kind: "agent") on pi agent-core + ai#18
inhaq merged 8 commits into
mainfrom
pi-native-agent-runner

Conversation

@inhaq

@inhaq inhaq commented Jun 15, 2026

Copy link
Copy Markdown
Owner

This pull request was created by @kiro-agent on behalf of @inhaq 👻

Comment with /kiro fix to address specific feedback or /kiro all to address everything.
Learn about Kiro Web


Adds PiAgentRunner — a third runner mechanism that gives loopwright a real inner agentic loop, built on @earendil-works/pi-agent-core + pi-ai. This is the strategic follow-on to #17.

Why

Until now the engine outsourced the inner loop:

  • CliRunner shells out to codex/kiro — the loop is opaque and the binary must be installed on PATH.
  • HttpRunner does a single /chat/completions call and cannot edit files — it just returns a diff as JSON.

PiAgentRunner owns the loop in-process: the model reads, lists, writes, edits, and runs shell commands through tools rooted at req.cwd (the task's git worktree). Any provider with an API key becomes a first-class file-editing actor — no external CLI required.

It pairs with the captureDiff seam from #17: because the agent edits the worktree on disk, the engine reviews the real git diff, so the model's self-reported diff is no longer trusted.

What's in it

  • New runner kind "agent" wired into RunnerProfileSchema and runnerFactory (the engine, state machine, scheduler, and roles are untouched — it's purely a new backend behind the existing AgentRunner interface).
  • Minimal, real toolset on top of pi's NodeExecutionEnv: read_file, list_dir, write_file, edit_file (unique-substring replace), bash (output redacted + truncated).
  • Profile options: provider, apiKeyEnv, thinkingLevel, maxTurns, timeoutMs, tools allowlist, maxOutputChars.
  • Cooperative cancellation (req.signal), a wall-clock timeout, and a turn cap all converge on agent.abort(); token usage is summed into meta.usage in the shape observability/events.ts normalizeUsage() already understands; quota/rate-limit errors set quotaExhausted.
  • Heavy collaborators (model, execution env, stream fn, API key) are injectable so the real loop runs offline in tests.

Testing

test/piAgentRunner.test.ts (7 tests) drives the real pi Agent loop and the real tools against pi's faux provider over a temp directory — no network or API key:

  • edits an existing file via edit_file and surfaces the final assistant text;
  • creates a new nested file via write_file;
  • recovers when a tool throws (non-unique edit_file) without crashing the run;
  • aborts a runaway tool loop at maxTurns;
  • respects a tool allowlist;
  • returns immediately on a pre-aborted signal;
  • is selected by createRunner for kind: "agent".

npm run typecheck clean; full suite green (195 tests).

Dependencies

Adds @earendil-works/pi-agent-core and @earendil-works/pi-ai (both MIT). These are the first runtime deps beyond zod; they're what provide the agent loop, the unified multi-provider transport, and the Node execution env.

Notes / follow-ups

  • Independent of Add JSON repair + review ground-truth worktree diff #17 at the code level (different files); they compose at runtime.
  • Desktop settings catalog (desktop/src/settings.ts) isn't wired to expose kind: "agent" yet — a small UI follow-up.
  • Natural next steps from the deep-dive: stream pi's tool_execution_* events into the SSE hub, and add beforeToolCall permission gating (no writes outside the worktree / no network).

Summary by CodeRabbit

  • New Features
    • Added a native agent runner type for multi-turn tool-calling workflows.
    • Introduced mid-call runner activity streaming (sub-step phases and tool/turn metadata).
    • Added transcript compaction options and configurable thinking/turn/output limits.
    • Added safety controls (workspace confinement + bash blocking) and tool allowlisting.
  • Bug Fixes
    • Improved cancellation, per-run timeout handling, and steering during active runs.
  • Tests
    • Expanded agent runner, safety gating, compaction, and role/activity streaming coverage.
  • Chores
    • Updated agent-related dependencies.

Introduce PiAgentRunner: a vendor-neutral AgentRunner that drives a real
multi-turn tool-calling loop in-process via @earendil-works/pi-agent-core
and pi-ai. Unlike CliRunner (opaque subprocess, requires codex/kiro on
PATH) and HttpRunner (a single chat completion that cannot edit files),
this runner owns the inner loop: the model reads, lists, writes, edits,
and runs shell commands through a minimal toolset (read_file, list_dir,
write_file, edit_file, bash) rooted at req.cwd (the task worktree). Any
provider with an API key becomes a first-class file-editing actor.

Pairs with the captureDiff seam: because the agent edits the worktree on
disk, the engine's git-diff capture reviews the real changes, so the
model's self-reported diff is no longer trusted.

- New runner kind "agent" in RunnerProfileSchema + runnerFactory.
- Profile options: provider, apiKeyEnv, thinkingLevel, maxTurns,
  timeoutMs, tools allowlist, maxOutputChars.
- Cooperative cancellation (req.signal), wall-clock timeout, and a turn
  cap all converge on agent.abort(); token usage is summed into meta in
  the shape observability normalizeUsage() already understands.
- Heavy collaborators (model, execution env, streamFn, api key) are
  injectable so the real loop + real tools are exercised offline.

Tests (test/piAgentRunner.test.ts, 7): drive the real Agent loop + real
tools against pi's faux provider over a temp dir \u2014 file edit, file
create, tool-error recovery, maxTurns abort, tool allowlist, pre-aborted
cancellation, and factory selection. Full suite green; typecheck clean.
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1ca16ed3-2039-462c-9163-34c3e6ba2109

📥 Commits

Reviewing files that changed from the base of the PR and between 63b838f and f2dff84.

📒 Files selected for processing (3)
  • src/runners/agentRunner.ts
  • src/runners/runnerFactory.ts
  • src/session.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/runners/runnerFactory.ts
  • src/session.ts
  • src/runners/agentRunner.ts

📝 Walkthrough

Walkthrough

Adds "agent" as a new RunnerKind, implements PiAgentRunner that wires @earendil-works/pi-agent-core and @earendil-works/pi-ai into a multi-turn agent loop with allowlisted workspace-confined tools, turn/timeout/output caps, quota detection, and transcript compaction. Extends the public API with activity event streaming (RunnerActivityEvent), wires it through role adapters and session persistence, and validates all behaviors with comprehensive Vitest suites including permission gating and bash safety.

Changes

PiAgentRunner multi-turn implementation with activity streaming

Layer / File(s) Summary
Public API contracts: runner kind, request/activity types, and event observability
src/runners/agentRunner.ts, src/observability/events.ts
Expands RunnerKind and RunnerProfileSchema to include "agent". Extends RunRequest with onEvent callback for mid-call activity streaming and steering callback for mid-run guidance. Introduces RunnerActivity interface for turn/tool phase events with optional metadata. Defines RunnerActivityEvent observability type with role/runner/model attribution, phase type, and optional tool/error/turn fields. Updates EVENT_TYPES with runnerActivity classifier.
Package dependencies and tool allowlist definitions
package.json, src/runners/piAgentRunner.ts
Adds @earendil-works/pi-agent-core and @earendil-works/pi-ai at ^0.79.3. Exports PI_AGENT_TOOL_NAMES allowlist (read_file, write_file, list_files, edit_file, bash) and PiAgentToolName type.
Safety policies and transcript compaction utilities
src/runners/piAgentRunner.ts
Defines SafetySchema with confineToCwd toggle (default on) and optional denyBashPattern regex for bash filtering. Implements findCompactionCut to compute turn-aligned transcript boundaries and createCompactionTransform to conditionally summarize middle sections when over context budget. Exports CompactionOptions type.
PiAgentRunner options schema and dependency injection
src/runners/piAgentRunner.ts
Defines PiAgentRunnerOptionsSchema with provider, apiKeyEnv, thinkingLevel, maxTurns, timeoutMs, tools allowlist, safety policy, compaction settings, and maxOutputChars. Exports PiAgentRunnerOptions type and PiAgentRunnerDeps interface for injectable model/env/stream/apiKey overrides.
PiAgentRunner constructor and helper methods
src/runners/piAgentRunner.ts
Implements constructor with eager schema validation. Defines system prompt constant, provider registration guard, assistant-text extractor, quota/rate-limit detector, and workspace containment check. Implements buildTools to instantiate allowlisted tools bound to ExecutionEnv with edit deduplication and bash redaction. Implements resolveModel and apiKey resolution chains checking injected overrides, options, then environment fallback.
PiAgentRunner.run() multi-turn execution and result finalization
src/runners/piAgentRunner.ts
Implements run() method: early-aborts on pre-aborted signal, creates ExecutionEnv, resolves model/api-key, wires compaction hook, constructs Agent with beforeToolCall safety gating (filesystem confinement + bash pattern blocking). Subscribes to agent events to count turns (aborting on maxTurns), emit tool/turn phases via req.onEvent, accumulate token usage, and capture quota error text. Registers abort listener and timeout. Integrates req.steering callback. Extracts final text, clamps to maxOutputChars, computes quotaExhausted, and returns RunResult with timing, turn/token counts, and cancellation/timeout/limit/block/steer flags.
Activity event streaming through role adapter enrichment
src/adapters/roleBindings.ts, src/adapters/runnerRoles.ts
Extends CreateRolesOptions, RunnerActorOptions, and RunnerCriticOptions with onActivity callback. Introduces activityForwarder helper to enrich RunnerActivityEvent with role ("actor"/"critic"), runnerId, and model before forwarding. RunnerActor and RunnerCritic precompute this.onEvent; all runner.run invocations conditionally pass { onEvent: this.onEvent } when configured.
Session persistence of runner activity and runner factory dispatch
src/session.ts, src/runners/runnerFactory.ts
Updates session.ts to conditionally record runnerActivity events to store (fire-and-forget with logged errors) or fall back to roleOpts.onActivity. Converts onRunnerCall persistence to fire-and-forget with logging. Updates runnerFactory.ts to dispatch profile.kind "agent" to new PiAgentRunner(profile).
Comprehensive test validation for compaction, PiAgentRunner, and activity streaming
test/piAgentCompaction.test.ts, test/piAgentRunner.test.ts, test/runnerRoles.test.ts
Vitest suites for compaction utilities (boundary correctness, budget-overflow, disabled compaction), core PiAgentRunner behaviors (file mutation, tool error propagation, maxTurns abortion, allowlist enforcement, pre-cancelled abort, factory dispatch, phase streaming), permission gating (filesystem confinement, absolute-path blocking, bash pattern matching, default bash exclusion, confineToCwd relaxation), steering (mid-run injection, zero-count verification), and activity streaming enrichment across actor/critic roles.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant PiAgentRunner
  participant Agent
  participant ExecutionEnv
  Caller->>PiAgentRunner: run(req)
  alt req.signal already aborted
    PiAgentRunner-->>Caller: RunResult (cancelled: true)
  else
    PiAgentRunner->>ExecutionEnv: create from req.cwd
    PiAgentRunner->>PiAgentRunner: resolveModel (register providers once)
    PiAgentRunner->>PiAgentRunner: wire compaction transformContext hook
    PiAgentRunner->>Agent: construct with tools and beforeToolCall safety
    PiAgentRunner->>PiAgentRunner: subscribe to events, register timeout/abort listener
    loop multi-turn until maxTurns or abort or signal
      Agent->>ExecutionEnv: tool call
      PiAgentRunner->>PiAgentRunner: beforeToolCall checks path/bash pattern
      alt blocked by confinement or regex
        PiAgentRunner->>PiAgentRunner: increment blockedToolCalls
      else allowed
        ExecutionEnv-->>Agent: tool result
      end
      req->>PiAgentRunner: onEvent (turn_start / tool_start / tool_end)
      PiAgentRunner->>PiAgentRunner: count turn, accumulate tokens
    end
    PiAgentRunner->>Agent: abort (maxTurns or timeout or signal)
    Agent-->>PiAgentRunner: final transcript
    PiAgentRunner->>PiAgentRunner: extract text, clamp, detect quota
    PiAgentRunner-->>Caller: RunResult
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • inhaq/loopwright#4: Extends role-binding layer (createRoles, RunnerActor/RunnerCritic) by adding mid-call activity streaming (onActivityRunnerActivityEvent) through the same runner→role wiring path.
  • inhaq/loopwright#5: Both extend src/runners/runnerFactory.ts createRunner switch to add new profile.kind dispatch cases ("agent"PiAgentRunner in main, "http"HttpRunner in retrieved).
  • inhaq/loopwright#8: Both extend observability event plumbing in src/observability/events.ts / roleBindings.ts / session.ts to add new event types and forwarding/persistence hooks (runnerActivity/onActivity in main, runner_call/onRunnerCall in retrieved).

Poem

🐇 A new agent bounds through the warren with flair,
With tools safely gated, beforeToolCall fair.
Turns counted and trimmed, context compacted tight,
Activity streaming flows left and right.
Steering through turns, quota warnings gleam bright—
The multi-turn dance takes flight! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a native agentic runner of kind 'agent' built on pi agent-core and ai libraries.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pi-native-agent-runner

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
test/piAgentRunner.test.ts (1)

113-120: ⚡ Quick win

Allowlist test should exercise a disallowed tool call.

This case currently never calls write_file, so it can pass even if allowlist enforcement breaks. Script a write_file tool call and assert the tool is rejected (and file is not created).

🤖 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 `@test/piAgentRunner.test.ts` around lines 113 - 120, The allowlist test in the
"respects a tool allowlist (write_file disabled)" case does not actually
exercise the disallowed tool, making it unable to catch allowlist enforcement
breakage. Modify the faux response in this test to script a write_file tool call
attempt (instead of "no tools used"), then add assertions to verify that the
write_file tool is rejected by the runner and that no file is created on disk.
This will properly validate that the allowlist is enforced when write_file is
excluded from the tools array.
🤖 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 `@src/runners/piAgentRunner.ts`:
- Around line 61-67: The bash tool is currently included in PI_AGENT_TOOL_NAMES
and enabled by default at lines 147-148, which creates a security risk for
prompt injection and data exfiltration. Remove bash from the PI_AGENT_TOOL_NAMES
constant at lines 61-67 to exclude it from default-enabled tools. Then update
the logic at lines 147-148 that enables all tools when tools is unset to only
include the file tools (read_file, list_dir, write_file, edit_file), allowing
bash to be added only when explicitly requested in the profile configuration.
The bash tool definition at lines 220-233 remains unchanged but will no longer
be included by default.
- Around line 301-306: The turns counter in the turn_start event handler is
incremented before checking against maxTurns, allowing one extra turn to execute
before the abort triggers. Move the limit check to occur before incrementing
turns, or change the condition from `turns > this.opts.maxTurns` to `turns >=
this.opts.maxTurns` and perform the check prior to the increment operation. This
ensures the maxTurns budget is enforced strictly without allowing an overshoot.

---

Nitpick comments:
In `@test/piAgentRunner.test.ts`:
- Around line 113-120: The allowlist test in the "respects a tool allowlist
(write_file disabled)" case does not actually exercise the disallowed tool,
making it unable to catch allowlist enforcement breakage. Modify the faux
response in this test to script a write_file tool call attempt (instead of "no
tools used"), then add assertions to verify that the write_file tool is rejected
by the runner and that no file is created on disk. This will properly validate
that the allowlist is enforced when write_file is excluded from the tools array.
🪄 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 Plus

Run ID: 6232505c-2e14-485f-aece-bd22f22594be

📥 Commits

Reviewing files that changed from the base of the PR and between e9052a7 and a797bf7.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • package.json
  • src/runners/agentRunner.ts
  • src/runners/piAgentRunner.ts
  • src/runners/runnerFactory.ts
  • test/piAgentRunner.test.ts

Comment thread src/runners/piAgentRunner.ts
Comment thread src/runners/piAgentRunner.ts
Enforce a tool-call permission policy via pi's beforeToolCall hook:
- confineToCwd (default on) blocks the file tools (read/list/write/edit)
  from touching paths that escape the worktree root, whether via absolute
  paths or .. traversal. A blocked call becomes an error tool result the
  model sees and can recover from, and is counted in meta.blockedToolCalls.
- denyBashPattern (optional regex) blocks matching bash commands, e.g.
  network egress like curl/wget.

confineToCwd guards the FILE tools only; bash stays inherently unconfined,
so the docs point at denyBashPattern + OS-level containment for real
isolation.

Tests (+5): parent-escape write blocked, absolute-path read blocked,
in-worktree paths allowed, denyBashPattern blocks curl, and confineToCwd:
false permits escapes \u2014 all against the real Agent loop via the faux
provider. typecheck clean; suite green.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
src/runners/piAgentRunner.ts (1)

73-107: 💤 Low value

ReDoS risk in denyBashPattern is config-gated but unmitigated.

The Zod refinement at lines 93-100 validates that denyBashPattern compiles as a regex, but does not guard against patterns that cause exponential backtracking (e.g., (a+)+$). Since this value comes from the runner profile (config/trusted source) rather than runtime user input, the attack surface is limited to profile authors. Still, consider adding a timeout or using a safe-regex library if untrusted configs are possible.

🤖 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/runners/piAgentRunner.ts` around lines 73 - 107, The denyBashPattern
field validation in SafetySchema only checks if the pattern compiles as a valid
regex but does not guard against patterns that could cause ReDoS (Regular
Expression Denial of Service) through exponential backtracking. Enhance the
.refine() method for the denyBashPattern field to include additional validation
that detects and rejects potentially dangerous regex patterns. This can be done
by using a safe-regex library or by implementing pattern analysis logic that
identifies problematic constructs like nested quantifiers. Update the error
message to clarify that the pattern must be both valid and safe from ReDoS
issues.

Source: Linters/SAST tools

🤖 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.

Nitpick comments:
In `@src/runners/piAgentRunner.ts`:
- Around line 73-107: The denyBashPattern field validation in SafetySchema only
checks if the pattern compiles as a valid regex but does not guard against
patterns that could cause ReDoS (Regular Expression Denial of Service) through
exponential backtracking. Enhance the .refine() method for the denyBashPattern
field to include additional validation that detects and rejects potentially
dangerous regex patterns. This can be done by using a safe-regex library or by
implementing pattern analysis logic that identifies problematic constructs like
nested quantifiers. Update the error message to clarify that the pattern must be
both valid and safe from ReDoS issues.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 64db2483-7cfe-4d7d-a868-c949662339d8

📥 Commits

Reviewing files that changed from the base of the PR and between a797bf7 and 197b50e.

📒 Files selected for processing (2)
  • src/runners/piAgentRunner.ts
  • test/piAgentRunner.test.ts

Three pi-harness Tier 3 features for the native agent runner.

G) Sub-step activity streaming. RunRequest gains an onEvent sink + a
vendor-neutral RunnerActivity type; PiAgentRunner forwards turn_start /
tool_start / tool_end from pi's agent events. The role layer
(runnerRoles) enriches each activity with role + runner identity and
threads onEvent into every runner.run() call; createRoles exposes
onActivity; session wires it to store.recordEvent(runner_activity),
which the server's store tap already fans to the SSE hub - so a monitor
sees the actor's tool calls live with no server.ts change.

D) Context compaction. PiAgentRunner gains a compaction option and wires
pi's transformContext + convertToLlm: when the transcript grows past
budget it summarizes the older middle via pi's generateSummary and keeps
the prompt + recent tail. findCompactionCut snaps the retained tail back
to a turn-start assistant so a toolResult is never orphaned. Exported for
direct testing.

E) Steering. RunRequest.steering hands the caller a steer(text) bound to
the live loop; PiAgentRunner injects it via agent.steer so a human can
nudge a running task (taking effect after the current turn) instead of
only cancelling. meta.steerCount reports injections.

Tests: runner-level activity emission + role enrichment/threading;
compaction cut + summarize/keep + no-trigger + too-short (vs faux); mid-
run steering proven to reach the next turn's context. Full suite 197
green; typecheck clean.
inhaq and others added 5 commits June 15, 2026 06:55
- bash is no longer default-enabled: profiles must explicitly allowlist
  it via the tools option. Default-on tools are read/list/write/edit
  only, shrinking the prompt-injection / exfiltration surface.
- maxTurns is now checked before incrementing the turn counter, so the
  cap is enforced strictly instead of overshooting by one turn.
- Tests updated: denyBashPattern test opts into bash; added a test
  asserting bash is excluded by default.

Addresses CodeRabbit review on PR #18.

Co-authored-by: Inzimam Ul Haq <27832433+inhaq@users.noreply.github.com>
The onActivity (and the identical onRunnerCall) sink dropped the Promise
from store.recordEvent, so a rejected persistence could surface as an
unhandled rejection and destabilize the run under strict settings. Make
the fire-and-forget intent explicit with void and catch failures, logging
via opts.log.

Addresses CodeRabbit review on PR #20.

Co-authored-by: Inzimam Ul Haq <27832433+inhaq@users.noreply.github.com>
Restacks Tier 3 onto the updated base (bash opt-in + maxTurns-before-
increment from PR #18 review). Resolves the piAgentRunner.ts turn_start
handler conflict by enforcing the turn cap before incrementing while
keeping the Tier 3 streaming emits (turn_start / tool_start / tool_end).

Co-authored-by: Inzimam Ul Haq <27832433+inhaq@users.noreply.github.com>
Tier 3 agent runner: streaming, compaction, steering
# Conflicts:
#	src/runners/agentRunner.ts
#	src/runners/runnerFactory.ts
@inhaq inhaq merged commit 29e1dce into main Jun 15, 2026
8 checks passed
@inhaq inhaq deleted the pi-native-agent-runner branch June 15, 2026 08:49
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.

1 participant