mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 14:34:47 +00:00
feat(session): raise ping-pong turn ceiling
Co-authored-by: Thirumalesh <thirumaleshpinninti@gmail.com>
This commit is contained in:
@@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Build: enable stricter Vitest lint rules for focused, disabled, conditional, hook, matcher, and expectation hazards.
|
||||
- Build: pin explicit oxfmt defaults in the shared formatter config to keep formatting behavior stable across upgrades.
|
||||
- TypeScript: enable stricter compiler checks for implicit returns, side-effect imports, overrides, and unused production code.
|
||||
- Agents: allow `session.agentToAgent.maxPingPongTurns` up to 20 while keeping the default at 5 for longer agent-to-agent reply chains. Fixes #52382. (#52400) Thanks @thirumaleshp.
|
||||
- Build: upgrade workspace package management to pnpm 11 and keep Docker, install, update, and release workflows on the pnpm 11 config surface. (#79414) Thanks @altaywtf.
|
||||
- Models: add provider-level `localService` startup for on-demand local model servers before OpenAI-compatible requests, including one-shot model probes.
|
||||
- Agents: trim default system prompt guidance and send-only message tool schemas to reduce prompt tokens while preserving GPT-5 personality guidance.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
c9e88800854b697cb3c9721d0087eb2bc7bcf6ae7239cb51d9849c49ef3d48e3 config-baseline.json
|
||||
67c58457ed2b525975cdb053489f92a5f840c8cf982666393e111fd327dd132e config-baseline.core.json
|
||||
1cc2cabc41c2261492dea4d927b48864c6992dcfb5b81fa97f2171848d037b1e config-baseline.json
|
||||
bfa974d070e5ef26fab023506b050cb3a582d1e54a096dbf4dddbc59535de29c config-baseline.core.json
|
||||
f90c9d96ccc4c0c703d6c489f86d89fde208cd7f697b396aeee96ff3ee087956 config-baseline.channel.json
|
||||
18f71e9d4a62fe68fbd5bf18d5833a4e380fc705ad641769e1cf05794286344c config-baseline.plugin.json
|
||||
|
||||
@@ -104,7 +104,8 @@ provenance. The receiving agent should treat them as tool-routed data, not as a
|
||||
direct end-user-authored instruction.
|
||||
|
||||
After the target responds, OpenClaw can run a **reply-back loop** where the
|
||||
agents alternate messages (up to 5 turns). The target agent can reply
|
||||
agents alternate messages (up to `session.agentToAgent.maxPingPongTurns`, range
|
||||
0-20, default 5). The target agent can reply
|
||||
`REPLY_SKIP` to stop early.
|
||||
|
||||
## Status and orchestration helpers
|
||||
|
||||
@@ -1219,7 +1219,7 @@ See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for preceden
|
||||
- **`reset`**: primary reset policy. `daily` resets at `atHour` local time; `idle` resets after `idleMinutes`. When both configured, whichever expires first wins. Daily reset freshness uses the session row's `sessionStartedAt`; idle reset freshness uses `lastInteractionAt`. Background/system-event writes such as heartbeat, cron wakeups, exec notifications, and gateway bookkeeping can update `updatedAt`, but they do not keep daily/idle sessions fresh.
|
||||
- **`resetByType`**: per-type overrides (`direct`, `group`, `thread`). Legacy `dm` accepted as alias for `direct`.
|
||||
- **`mainKey`**: legacy field. Runtime always uses `"main"` for the main direct-chat bucket.
|
||||
- **`agentToAgent.maxPingPongTurns`**: maximum reply-back turns between agents during agent-to-agent exchanges (integer, range: `0`–`5`). `0` disables ping-pong chaining.
|
||||
- **`agentToAgent.maxPingPongTurns`**: maximum reply-back turns between agents during agent-to-agent exchanges (integer, range: `0`-`20`, default: `5`). `0` disables ping-pong chaining.
|
||||
- **`sendPolicy`**: match by `channel`, `chatType` (`direct|group|channel`, with legacy `dm` alias), `keyPrefix`, or `rawKeyPrefix`. First deny wins.
|
||||
- **`maintenance`**: session-store cleanup + retention controls.
|
||||
- `mode`: `warn` emits warnings only; `enforce` applies cleanup.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import { createSessionConversationTestRegistry } from "../../test-utils/session-conversation-registry.js";
|
||||
import { resolveAnnounceTargetFromKey } from "./sessions-send-helpers.js";
|
||||
import { resolveAnnounceTargetFromKey, resolvePingPongTurns } from "./sessions-send-helpers.js";
|
||||
|
||||
describe("resolveAnnounceTargetFromKey", () => {
|
||||
beforeEach(() => {
|
||||
@@ -63,3 +63,28 @@ describe("resolveAnnounceTargetFromKey", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolvePingPongTurns", () => {
|
||||
it("defaults to 5 when unset", () => {
|
||||
expect(resolvePingPongTurns(undefined)).toBe(5);
|
||||
expect(resolvePingPongTurns({ session: {} } as never)).toBe(5);
|
||||
});
|
||||
|
||||
it("uses configured values through the 20-turn ceiling", () => {
|
||||
expect(
|
||||
resolvePingPongTurns({ session: { agentToAgent: { maxPingPongTurns: 10 } } } as never),
|
||||
).toBe(10);
|
||||
expect(
|
||||
resolvePingPongTurns({ session: { agentToAgent: { maxPingPongTurns: 20 } } } as never),
|
||||
).toBe(20);
|
||||
});
|
||||
|
||||
it("keeps defensive floor and ceiling clamps", () => {
|
||||
expect(
|
||||
resolvePingPongTurns({ session: { agentToAgent: { maxPingPongTurns: -1 } } } as never),
|
||||
).toBe(0);
|
||||
expect(
|
||||
resolvePingPongTurns({ session: { agentToAgent: { maxPingPongTurns: 50 } } } as never),
|
||||
).toBe(20);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ export {
|
||||
} from "./sessions-send-tokens.js";
|
||||
|
||||
const DEFAULT_PING_PONG_TURNS = 5;
|
||||
const MAX_PING_PONG_TURNS = 5;
|
||||
const MAX_PING_PONG_TURNS = 20;
|
||||
|
||||
export type AnnounceTarget = {
|
||||
channel: string;
|
||||
|
||||
@@ -1537,7 +1537,7 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"session.agentToAgent":
|
||||
"Groups controls for inter-agent session exchanges, including loop prevention limits on reply chaining. Keep defaults unless you run advanced agent-to-agent automation with strict turn caps.",
|
||||
"session.agentToAgent.maxPingPongTurns":
|
||||
"Max reply-back turns between requester and target agents during agent-to-agent exchanges (0-5). Use lower values to hard-limit chatter loops and preserve predictable run completion.",
|
||||
"Max reply-back turns between requester and target agents during agent-to-agent exchanges (0-20, default 5). Use lower values to hard-limit chatter loops and preserve predictable run completion.",
|
||||
"session.threadBindings":
|
||||
"Shared defaults for thread-bound session routing behavior across providers that support thread focus workflows. Configure global defaults here and override per channel only when behavior differs.",
|
||||
"session.threadBindings.enabled":
|
||||
|
||||
@@ -205,7 +205,7 @@ export type SessionConfig = {
|
||||
/** Session transcript write-lock acquisition policy. */
|
||||
writeLock?: SessionWriteLockConfig;
|
||||
agentToAgent?: {
|
||||
/** Max ping-pong turns between requester/target (0–5). Default: 5. */
|
||||
/** Max ping-pong turns between requester/target (0-20). Default: 5. */
|
||||
maxPingPongTurns?: number;
|
||||
};
|
||||
/** Shared defaults for thread-bound session routing across channels/providers. */
|
||||
|
||||
@@ -64,7 +64,7 @@ export const SessionSchema = z
|
||||
.optional(),
|
||||
agentToAgent: z
|
||||
.object({
|
||||
maxPingPongTurns: z.number().int().min(0).max(5).optional(),
|
||||
maxPingPongTurns: z.number().int().min(0).max(20).optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
|
||||
Reference in New Issue
Block a user