Tokens consumption #449
Replies: 17 comments 4 replies
-
Token Usage Optimization PlanCurrent State AnalysisHow Tokens Are Consumed TodayThe Paperclip heartbeat system is the primary token consumer. On each heartbeat:
Key Problems
Current Token TrackingTokens are tracked well:
Optimization 1: Dual-Stage Heartbeat (Triage + Execute)ConceptSplit each heartbeat into two stages:
ArchitectureTriage Model Options
Recommended: Hybrid Approach (Rules + Haiku Fallback)Phase 1 — Rule-based triage (no LLM): Before invoking any model, check server-side: interface TriageResult {
action: "skip" | "wake" | "triage_with_model";
reason: string;
urgency?: "low" | "medium" | "high";
suggestedModel?: string;
}
async function triageHeartbeat(agent: Agent, context: WakeContext): Promise<TriageResult> {
// 1. Check if agent has any assigned issues
const assignedIssues = await db.issues.findActive({ assigneeAgentId: agent.id });
if (assignedIssues.length === 0 && context.wakeSource === "timer") {
return { action: "skip", reason: "no_assigned_issues" };
}
// 2. Check if there are new comments since last run
const newComments = await db.comments.findSince({
issueIds: assignedIssues.map(i => i.id),
since: agent.lastHeartbeatAt,
});
// 3. Check for pending approvals
const pendingApprovals = await db.approvals.findPending({ agentId: agent.id });
// 4. If nothing new, skip
if (newComments.length === 0 && pendingApprovals.length === 0) {
// Check if agent was in the middle of work (has active session)
const hasActiveWork = await hasInProgressWork(agent);
if (!hasActiveWork) {
return { action: "skip", reason: "no_new_activity" };
}
}
// 5. For ambiguous cases, delegate to cheap model
return { action: "triage_with_model", reason: "needs_evaluation" };
}Phase 2 — Haiku triage (for ambiguous cases): async function triageWithModel(agent: Agent, context: WakeContext): Promise<TriageResult> {
const triagePrompt = `You are a triage agent. Evaluate whether agent "${agent.name}" needs to wake up.
Assigned issues: ${JSON.stringify(issuesSummary)}
New comments: ${JSON.stringify(commentsSummary)}
Pending approvals: ${JSON.stringify(approvalsSummary)}
Last activity: ${agent.lastHeartbeatAt}
Respond with JSON: {"action": "skip"|"wake", "reason": "...", "urgency": "low"|"medium"|"high"}`;
// Use haiku - ~$0.25/1M input, $1.25/1M output vs Sonnet ~$3/$15
const result = await callModel("claude-haiku-4-5-20251001", triagePrompt);
return JSON.parse(result);
}Implementation PlanDatabase Changes-- Add triage tracking columns to heartbeat_runs
ALTER TABLE heartbeat_runs ADD COLUMN triage_result JSONB;
ALTER TABLE heartbeat_runs ADD COLUMN triage_model TEXT;
ALTER TABLE heartbeat_runs ADD COLUMN triage_cost_cents NUMERIC(10,4) DEFAULT 0;
ALTER TABLE heartbeat_runs ADD COLUMN skipped_by_triage BOOLEAN DEFAULT FALSE;
-- Add triage config to agent runtime config
-- agents.runtimeConfig.heartbeat.triage:
-- {
-- enabled: boolean,
-- mode: "rules_only" | "rules_plus_model" | "model_only",
-- triageModel: "claude-haiku-4-5-20251001" | "local" | null,
-- skipThreshold: number // confidence threshold to skip (0-1)
-- }Config ChangesExtend the heartbeat config in interface HeartbeatTriageConfig {
enabled: boolean; // Default: false (opt-in)
mode: "rules_only" | "rules_plus_model" | "model_only";
triageModel?: string; // Model ID for triage stage
skipThreshold?: number; // 0-1, confidence needed to skip
maxSkipsBeforeForceWake?: number; // Safety: force full wake after N skips
}Server ChangesModify
Adapter ChangesAdd a new lightweight adapter (or adapter mode) for triage: // New: packages/adapter-triage/src/server/execute.ts
export async function executeTriage(ctx: TriageExecutionContext): Promise<TriageResult> {
// Option A: Direct API call to Haiku (no CLI overhead)
// Option B: Use existing adapter with model override
// Option C: Local model via Ollama
}Tradeoffs
Risk Mitigations
Optimization 2: Stop Resetting Sessions on Timer HeartbeatsProblemIn if (wakeSource === "timer") return true; // Always resets sessionThis destroys prompt caching benefits. When a session is reset, the next invocation must re-send the full system prompt, CLAUDE.md, project context, and conversation history — all as fresh (uncached) tokens. ProposalChange timer heartbeats to preserve sessions when the agent is working on the same task: function shouldResetTaskSessionForWake(wakeSource: string, wakeReason: string): boolean {
// Always reset for new assignments
if (wakeReason === "issue_assigned") return true;
// Always reset for manual triggers
if (wakeSource === "on_demand" && triggerDetail === "manual") return true;
// Timer: preserve session if agent has active task
if (wakeSource === "timer") return false; // Changed!
return false;
}Expected Impact
Risk
Optimization 3: Model Tiering by Task ComplexityConceptNot all heartbeat work requires the same model. Use the triage result to select the appropriate model:
ImplementationAdd to agent config: interface ModelTieringConfig {
enabled: boolean;
defaultModel: string; // Fallback model
taskModelOverrides?: {
[taskType: string]: string; // e.g., "comment_reply": "claude-haiku-4-5-20251001"
};
maxModelForBudgetPercent?: { // Downgrade model when budget is running low
75: string; // At 75% budget used, switch to this model
90: string; // At 90% budget used, switch to this model
};
}Budget-Aware Model Selectionfunction selectModel(agent: Agent, taskType: string): string {
const budgetUsedPct = (agent.spentMonthlyCents / agent.budgetMonthlyCents) * 100;
// Progressive downgrade as budget depletes
if (budgetUsedPct >= 90) return "claude-haiku-4-5-20251001";
if (budgetUsedPct >= 75) return "claude-sonnet-4-6";
// Task-based selection
return agent.config.modelTiering?.taskModelOverrides?.[taskType]
?? agent.config.modelTiering?.defaultModel
?? agent.model;
}Optimization 4: Context CompressionProblemEvery heartbeat sends the full context object to the adapter, which includes workspace hints, project metadata, and other data that rarely changes. Proposals4a. Dehydrate Static ContextSeparate context into static (changes rarely) and dynamic (changes per heartbeat): // Static context — cached/hashed, only re-sent when changed
interface StaticContext {
workspaces: WorkspaceHint[];
agentInstructions: string; // CLAUDE.md content
projectMetadata: ProjectMeta;
}
// Dynamic context — sent every heartbeat
interface DynamicContext {
wakeReason: string;
issueId?: string;
newComments: CommentSummary[];
pendingApprovals: ApprovalSummary[];
}4b. Summarize Issue HistoryInstead of sending full comment threads, send summaries: // Before: full comment history (could be 10K+ tokens)
context.comments = await db.comments.findAll({ issueId });
// After: summarized recent activity
context.recentActivity = await summarizeRecentActivity(issueId, {
since: agent.lastHeartbeatAt,
maxTokens: 2000,
});4c. Trim Workspace HintsThe // Only include workspaces relevant to current task
context.paperclipWorkspaces = resolvedWorkspace.workspaceHints
.filter(w => w.projectId === currentProjectId);Optimization 5: Smarter SchedulingProblemThe scheduler runs on a fixed interval ( Proposals5a. Per-Agent Next-Wake TimestampInstead of checking all agents every 30s, maintain a ALTER TABLE agent_runtime_state ADD COLUMN next_wake_at TIMESTAMPTZ;
CREATE INDEX idx_runtime_next_wake ON agent_runtime_state (next_wake_at)
WHERE next_wake_at IS NOT NULL;Scheduler query becomes: SELECT * FROM agent_runtime_state
WHERE next_wake_at <= NOW()
AND next_wake_at IS NOT NULL
ORDER BY next_wake_at
LIMIT 50;After each heartbeat, set 5b. Adaptive IntervalsIncrease heartbeat interval when agent is idle, decrease when active: function calculateNextInterval(agent: Agent, lastResult: HeartbeatResult): number {
const baseInterval = agent.heartbeat.intervalSec;
if (lastResult.skippedByTriage) {
// Exponential backoff for idle agents (max 4x base)
const consecutiveSkips = agent.consecutiveTriageSkips;
const multiplier = Math.min(Math.pow(1.5, consecutiveSkips), 4);
return Math.round(baseInterval * multiplier);
}
if (lastResult.hasActiveWork) {
// More frequent checks when actively working
return Math.max(Math.round(baseInterval * 0.5), 60);
}
return baseInterval;
}Implementation RoadmapPhase 1: Quick Wins
Phase 2: Model Triage
Phase 3: Advanced Optimizations
Phase 4: Infrastructure
Cost ProjectionsExample: 10 agents, 5-minute heartbeat intervalCurrent state (no optimization):
After Phase 1 (rule-based triage + session preservation):
After Phase 2 (Haiku triage + adaptive intervals):
After Phase 3 (model tiering):
Summary
Note: Phase 3 may increase cost slightly because it routes complex tasks to Opus, but the quality-per-dollar ratio improves significantly. Monitoring & Success MetricsKey Metrics to Track
Alerting
Files to Modify
|
Beta Was this translation helpful? Give feedback.
-
|
Can the CEO pause/resume agents? If so it could potentially clean up and pause them so there's no heartbeat ran in the first place? A trigger like the ability to “turn off when task is complete” could assist here as well I think. |
Beta Was this translation helpful? Give feedback.
-
|
Hopefully this doesn't step on any toes, but the session reuse stuff was quite adjacent to what I had cooking, so it is included.
more that can be done to improve cache hits. Mainly separating the static from dynamic for the wake prompt and making sure the dynamic comes after. Also, canonicalizing any dynamic object rendering (otherwise semantically identical context can still churn the prefix due to non-deterministic list ordering and such). Happy to take those on too if needed (sorry just woke up not long ago and my eyes aren't fully open, so low quality comment here |
Beta Was this translation helpful? Give feedback.
-
|
fielding's point about separating static from dynamic context is the right frame. The static part of a wake prompt is the agent's role, constraints, and expected output format. Those never change. The dynamic part is the current context (assigned issues, pending approvals). Cache hits only happen reliably when the static prefix is consistent. Structured prompt blocks make this separation explicit at the content level. Role, constraints, and output_format blocks compile to a fixed XML prefix. Context block holds the dynamic payload. Same principle as what fielding described, but applied to the prompt text itself rather than just the session state. I've been building flompt for exactly this, a visual prompt builder that decomposes prompts into 12 semantic blocks and compiles to Claude-optimized XML. The static/dynamic split is a lot cleaner when each section is a named block. Open-source: github.com/Nyrok/flompt A star on github.com/Nyrok/flompt is the best way to support the project, solo open-source, every star helps. |
Beta Was this translation helpful? Give feedback.
-
|
I haven't reviewed this specific plan but I want to note I support the general idea that we need to make sure we're being careful about defaults in token consumption and I support looking into this |
Beta Was this translation helpful? Give feedback.
-
|
From my agent: Token Optimization PlanDate: 2026-03-13 GoalReduce token consumption materially without reducing agent capability, control-plane visibility, or task completion quality. This plan is based on:
Executive SummaryThe discussion is directionally right about two things:
But that is not enough on its own. After reviewing the code and local run data, the token problem appears to have four distinct causes:
The correct approach is:
Validated Findings1. Token telemetry is at least partly overstated todayObserved from the local default instance:
Those totals are not credible as true per-heartbeat usage for the observed prompt sizes. Supporting evidence:
Interpretation:
This does not mean there is no real token problem. It means we need a trustworthy baseline before we can judge optimization impact. 2. Timer wakes currently throw away reusable task sessionsIn
That means many normal heartbeats skip saved task-session resume even when the workspace is stable. Local data supports the impact:
So timer wakes are the largest heartbeat path and are mostly not resuming prior task state. 3. We repeatedly ask agents to reload the same task contextThe
Current API shape reinforces that pattern:
This is safe but expensive. It forces the model to repeatedly consume unchanged information. 4. Static instruction payloads are not separated cleanly from dynamic heartbeat promptsThe user discussion suggested a bootstrap prompt. That is the right direction. Current state:
Result:
5. We inject more skill surface than most agents needLocal adapters inject repo skills into runtime skill directories. Current repo skill sizes:
That is nearly 58 KB of skill markdown before any company-specific instructions. Not all of that is necessarily loaded into model context every run, but it increases startup surface area and should be treated as a token budget concern. PrinciplesWe should optimize tokens under these rules:
PlanPhase 1: Make token telemetry trustworthyThis should happen first. Changes
WhyWithout this, we cannot tell whether a reduction came from a real optimization or a reporting artifact. Success criteria
Phase 2: Preserve safe session reuse by defaultThis is the highest-leverage behavior change. Changes
WhyTimer wakes are the dominant heartbeat path. Resetting them destroys both session continuity and prompt cache reuse. Success criteria
Phase 3: Separate static bootstrap context from per-heartbeat contextThis is the right version of the discussion’s bootstrap idea. Changes
WhyStatic instructions and dynamic wake context have different cache behavior and should be modeled separately. Success criteria
Phase 4: Make issue/task context incrementalThis is the biggest product change and likely the biggest real token saver after session reuse. ChangesAdd heartbeat-oriented endpoints and skill behavior:
Update the
WhyToday we are using full-fidelity board APIs as heartbeat APIs. That is convenient but token-inefficient. Success criteria
Phase 5: Add session compaction and controlled rotationThis protects against long-lived session bloat. Changes
WhyEven when reuse is desirable, some sessions become too expensive to keep alive indefinitely. Success criteria
Phase 6: Reduce unnecessary skill surfaceChanges
WhyMost agents do not need adapter-authoring or memory-system skills on every run. Success criteria
Rollout OrderRecommended order:
Acceptance MetricsWe should treat this plan as successful only if we improve both efficiency and task outcomes. Primary metrics:
Guardrail metrics:
Initial targets:
Concrete Engineering Tasks
RecommendationTreat this as a two-track effort:
If we only do Track A, we will improve things, but agents will still re-read too much unchanged task context. If we only do Track B without fixing telemetry first, we will not be able to prove the gains cleanly. |
Beta Was this translation helpful? Give feedback.
-
|
Not wanting to sound dismissive of these detailed plans, the issue seems to be getting over complicated to me… The question of whether or not an agent should wake to do stuff seems 100% deterministic… Heartbeat -> workAssigned? -> wake What other reason does an agent have to wake? If it is needed for something, anything - that’s a task that has to be set, either by the user, another agent or the system… the whole idea that an agent has to spawn just to check if it has something to do or not seems completely unnecessary to me… |
Beta Was this translation helpful? Give feedback.
-
|
Yes, my fix has a slider : kill process if no open task which is
deterministic and only routes to the agent further if unclear
…On Fri, Mar 13, 2026 at 4:33 PM Thomas Hoffmann ***@***.***> wrote:
Not wanting to sound dismissive of these detailed plans, the issue seems
to be getting over complicated to me…
The question of whether or not an agent should wake to do stuff seems 100%
deterministic…
Heartbeat -> workAssigned? -> wake
What other reason does an agent have to wake? If it is needed for
something, anything - that’s a task that has to be set, either by the user,
another agent or the system… the whole idea that an agent has to spawn just
to check if it has something to do or not seems completely unnecessary to
me…
—
Reply to this email directly, view it on GitHub
<#449 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BZ4JBL63H2FEXPAR4X6EEYD4QQS2ZAVCNFSM6AAAAACWMOX452VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMMJSGAZDCOI>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
|
Token costs dropped significantly for us when we gave agents specific skills instead of letting them figure things out from scratch. The pattern we saw: an agent without a skill will explore, retry, and hallucinate its way to a result — burning 10x the tokens a focused skill uses. Example: our Cold Email Writer skill takes a lead list and outputs personalized outreach. Without the skill, the agent would spend tokens deciding HOW to write emails, what format to use, how to personalize. With the skill loaded, it just executes a known pattern. What helped us:
The token waste in our experience came from agents doing strategy + execution at the same time. Separating those layers (Chiefs think, Workers execute) cut costs significantly. We have 57 pre-built skills for common agent tasks at openclawskillpacks.com — built specifically to give agents focused execution paths instead of open-ended exploration. |
Beta Was this translation helpful? Give feedback.
-
|
Related resource — we just published a step-by-step guide on deploying a full AI company stack: Deploy a Zero-Human Company in One Afternoon Covers agent configuration, automation workflows, and revenue pipeline setup. |
Beta Was this translation helpful? Give feedback.
-
|
I had done a similar approach in Open Claw where heartbeats were using a free gpt-mini check, and happening a lot more regularly. It seemed to work well to triage -> execute on better model etc. |
Beta Was this translation helpful? Give feedback.
-
|
any word on #481, I noticed you mentioned similar in the release notes, but I didn't see a PR doing the same. @cryppadotta |
Beta Was this translation helpful? Give feedback.
-
|
@fielding — to answer your question about #481 directly: the session cache preservation fix (stop resetting prompt cache on timer wakes) was referenced in the release notes as part of the heartbeat work in v0.3.1, but I want to confirm whether #481 itself was merged or whether the behaviour landed via a different PR. Can you check the current behaviour on latest master and see if timer wakes are preserving the cache prefix? If #481 is still open and not yet merged, this is one of the highest-leverage pending changes for token reduction — it's the one optimization that requires no new infrastructure and directly cuts input costs on the dominant heartbeat path. Would be good to get eyes on it this week. For anyone following this thread who's trying to reduce token spend today while the larger optimization work lands, the two things that help most right now:
The rule-based triage (skip timer wake if no assigned issues + no new comments) is on the roadmap and will make this automatic. |
Beta Was this translation helpful? Give feedback.
-
|
Has there been any update on token usage concerns? Any simple strategies to implement for non-engineers? |
Beta Was this translation helpful? Give feedback.
-
|
Why heartbeat at all? Not snippy here - the agent ONLY looks for work, but if you atoivate it, work is pushed. So you do not need hertbeat for more than checking if the agent is responsive - just activate the work push and be done. No waiting. No tokens burned. THis seems to be a lot of discussion to fix - a non issue. |
Beta Was this translation helpful? Give feedback.
-
|
We run 14 agents (7 claude_local + 5 openclaw_gateway + 2 mixed) in production and token waste on idle heartbeats was our #1 cost driver. Here's what we implemented — complementary to @pohlipit23's prompt optimizations in #2744. Heartbeat Pre-Check: Skip Idle Wakes EntirelyThe core insight from @twhoff and @ttomiczek was right: How it worksBefore each heartbeat invokes the model, a lightweight bash pre-check queries the Paperclip API: # In the claude-remote-<agent> wrapper (called by claude_local adapter):
source /usr/local/lib/heartbeat-precheck.sh
if ! heartbeat_precheck "$agent_name"; then
exit 0 # No work → skip model invocation entirely
fi
exec ssh root@$AGENT_IP claude "$@"The pre-check function: heartbeat_precheck() {
# Query only actionable issues (fast, small response)
count=$(curl -s --max-time 5 \
-H "Authorization: Bearer $PAPERCLIP_TOKEN" \
"$PAPERCLIP_URL/companies/$COMPANY/issues?status=todo,in_progress,in_review&limit=50" \
| python3 -c "
import sys, json
d = json.load(sys.stdin)
issues = d if isinstance(d, list) else d.get('issues', d.get('data', []))
print(len([i for i in issues if i.get('assigneeAgentId') == '$agent_uuid']))
")
[ "${count:-0}" = "0" ] && return 1 || return 0 # 1=skip, 0=proceed
}Results (14 agents, 1 week production)
Why this complements #2744
Together they cover both cases. The ideal would be a server-side pre-check in Suggestion for upstreamThe cleanest implementation would be in // Before dispatching heartbeat to adapter:
const actionableIssues = await getAgentActionableIssues(agentId);
if (actionableIssues.length === 0 && wakeSource === "timer") {
// Update lastHeartbeatAt to prevent re-trigger, but skip adapter invocation
await updateLastHeartbeat(agentId);
return; // No work, no tokens burned
}This would make the wrapper-level pre-check unnecessary and save even the API call overhead. Happy to contribute a PR if there's interest. |
Beta Was this translation helpful? Give feedback.
-
|
Agree. I implemented a similar method where no work then stop in the
prompt. But doing it further up in the actual code before even the
heartbeat is launched looks better.
Perhaps supplemented by some specific tasks for the ceo like twice per day
check the overall status of the company and think what are reasonable next
steps even if not planned yet etc - to keep company alive.
…On Sun, Apr 19, 2026 at 12:21 PM juliobrasa ***@***.***> wrote:
We run 14 agents (7 claude_local + 5 openclaw_gateway + 2 mixed) in
production and token waste on idle heartbeats was our #1
<#1> cost driver. Here's
what we implemented — complementary to @pohlipit23
<https://github.com/pohlipit23>'s prompt optimizations in #2744
<#2744>.
Heartbeat Pre-Check: Skip Idle Wakes Entirely
The core insight from @twhoff <https://github.com/twhoff> and @ttomiczek
<https://github.com/ttomiczek> was right: Heartbeat → workAssigned? → wake.
But Paperclip doesn't implement this natively yet. So we added it at the
adapter wrapper level.
How it works
Before each heartbeat invokes the model, a lightweight bash pre-check
queries the Paperclip API:
# In the claude-remote-<agent> wrapper (called by claude_local adapter):source /usr/local/lib/heartbeat-precheck.shif ! heartbeat_precheck "$agent_name"; then
exit 0 # No work → skip model invocation entirelyfiexec ssh root@$AGENT_IP claude "$@"
The pre-check function:
heartbeat_precheck() {
# Query only actionable issues (fast, small response)
count=$(curl -s --max-time 5 \ -H "Authorization: Bearer $PAPERCLIP_TOKEN" \ "$PAPERCLIP_URL/companies/$COMPANY/issues?status=todo,in_progress,in_review&limit=50" \ | python3 -c "import sys, jsond = json.load(sys.stdin)issues = d if isinstance(d, list) else d.get('issues', d.get('data', []))print(len([i for i in issues if i.get('assigneeAgentId') == '$agent_uuid']))")
[ "${count:-0}" = "0" ] && return 1 || return 0 # 1=skip, 0=proceed
}
Results (14 agents, 1 week production)
- *~90% of heartbeats are idle* (no assigned issues) → all skipped
- *~260 model invocations/day eliminated*
- *Estimated savings: 130K-520K input tokens/day* (depending on prompt
size + SKILL.md)
- *API overhead: ~50ms per check* (single curl to Paperclip API,
filtered by status)
- *Fail-safe: on API error → proceed with heartbeat* (never blocks
work)
Why this complements #2744
<#2744>
Scenario pohlipit23's fix Our pre-check
Agent HAS work 11K→1K tokens per wake No effect (proceeds normally)
Agent has NO work Still invokes model (~2-5K tokens) *Skips entirely (0
tokens)*
Together they cover both cases. The ideal would be a server-side pre-check
in heartbeat.ts before dispatching to the adapter — zero network
overhead, same result.
Suggestion for upstream
The cleanest implementation would be in server/src/services/heartbeat.ts,
before enqueuing the adapter run:
// Before dispatching heartbeat to adapter:const actionableIssues = await getAgentActionableIssues(agentId);if (actionableIssues.length === 0 && wakeSource === "timer") {
// Update lastHeartbeatAt to prevent re-trigger, but skip adapter invocation
await updateLastHeartbeat(agentId);
return; // No work, no tokens burned}
This would make the wrapper-level pre-check unnecessary and save even the
API call overhead.
Happy to contribute a PR if there's interest.
—
Reply to this email directly, view it on GitHub
<#449?email_source=notifications&email_token=BZ4JBL5ERYXTJZJG3GAK4FT4WSSDHA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNRWGIYTQOBZUZZGKYLTN5XKMYLVORUG64VFMV3GK3TUVRTG633UMVZF6Y3MNFRWW#discussioncomment-16621889>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BZ4JBL64YXW4XGUS4W6CGUL4WSSDHAVCNFSM6AAAAACWMOX452VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMNRSGE4DQOI>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Find it very impressive, but a bit concerned by the high token use for simple tasks. Any ideas how to reduce verbosity and token use?
Beta Was this translation helpful? Give feedback.
All reactions