Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

 
 

Repository files navigation

Clarity Voicing

Unslop for custom agents

Clarity Voicing (CV) measures the repetitive defaults in an agent's user-facing responses, turns the findings into an agent-specific voice profile, and can apply that profile to every final response through Tau.

When to use it

Use CV when a custom agent is doing the right work but its final responses still sound generic, repetitive, over-structured, or unlike the person it is supposed to represent. It is especially useful when:

  • the agent already has real transcripts that expose habits synthetic prompts miss;
  • the same openings, summaries, handbacks, disclaimers, formatting, or jargon recur across otherwise unrelated turns;
  • the agent has standing instructions or reader preferences that must be protected while the repetitive defaults are removed; or
  • the voice rules must apply to every final response, not only when the model decides to load a writing skill.

Use the Tau integration when you need enforcement at delivery time. Tau 0.57.0's BeforeFinalOutput hook gives Unslop the completed, tool-free draft before the TUI displays or persists it. The adapter runs a separate tool-free Tau editor with the selected voice profile and returns one replacement message.

This is not a repair for incorrect reasoning, failed tool calls, missing facts, or a broken structured-output contract. The finalizer is instructed to preserve facts, decisions, refusals, evidence limits, names, dates, amounts, identifiers, URLs, code, and references. It also adds one model call to each finalized turn, so use it where consistent user-facing voice justifies that latency and cost.

How to use it with a custom Tau agent

1. Install ClarifyVoicing and Tau

Clone this fork and install Tau 0.57.0 or newer from PyPI:

git clone https://github.com/Nuosis/ClarifyVoicing.git
cd ClarifyVoicing

uv tool install --force 'tau-by-clarity>=0.57.0'
tau --version

The optional Tau integration dependency is also recorded in requirements-tau.txt as tau-by-clarity>=0.57.0. In a project-managed Python environment, install it with either command:

uv add 'tau-by-clarity>=0.57.0'
# or
python3 -m pip install 'tau-by-clarity>=0.57.0'

Python 3.10 or newer runs both unslop.py and the hook adapter. Claude Code is required only when generating or analyzing a profile; applying an existing profile uses Python and the installed Tau executable.

2. Choose or generate the agent's profile

Start with a profile under profiles/, or generate one from the agent's own output using the workflow below. Copy the chosen profile into a stable path owned by the custom agent:

mkdir -p /absolute/path/to/custom-agent/.tau
cp profiles/writing.md /absolute/path/to/custom-agent/.tau/voice-profile.md

Use a profile derived for that agent and reader whenever possible. A broad writing profile can remove common defaults, but it cannot encode a particular agent's role, vocabulary, or the reader's stated preferences.

3. Install the final-output hook into that agent

From the ClarifyVoicing repository, run:

python3 hooks/tau/install.py \
  --agent-root /absolute/path/to/custom-agent \
  --profile /absolute/path/to/custom-agent/.tau/voice-profile.md \
  --tau-command "$(command -v tau)" \
  --provider openai \
  --model gpt-5.4-mini \
  --thinking low

--agent-root is the directory from which the custom agent runs. The installer merges a command named unslop_before_final_output into <agent-root>/.tau/hooks.json; it preserves unrelated hooks and replaces an older Unslop hook when rerun.

The provider, model, and thinking flags configure the separate finalizer call, not the custom agent's main model. Choose a combination supported by the local Tau installation. The finalizer inherits Tau authentication from the calling agent, but runs without tools, extensions, skills, context-file discovery, or a session of its own. It uses a temporary home and working directory so it cannot rediscover and recursively call the custom agent's hook.

The generated hook command contains absolute paths to this repository and the profile. Rerun the installer after moving either one.

4. Run the custom agent and verify the delivered response

Launch Tau from the agent root as usual:

cd /absolute/path/to/custom-agent
tau

Exercise a response that contains facts which must survive and voice patterns the profile should remove. Confirm both of these outputs:

  1. The Tau TUI shows one rewritten assistant response with every fact intact.
  2. The new Tau session JSONL contains the same rewritten response and does not contain an emitted copy of the original draft.

Hook failures are fail-open: Tau delivers the original draft instead of suppressing the response. Test installation in a temporary copy of the agent before enabling it in a deployed agent. The paired baseline/hooked protocol, artifact verifier, and latest local result are under evals/tau-before-final-output/.

How to generate an agent-specific profile

Prefer real final responses when they exist

For Claude Code or Codex transcripts, harvest only the final messages a person actually saw, then analyze them with the agent's standing instructions and the reader's preferences:

python3 unslop.py \
  --domain "customer-facing responses from MyAgent" \
  --corpus codex \
  --corpus-root /absolute/path/to/transcripts \
  --directives /absolute/path/to/custom-agent/.tau/SYSTEM.md \
  --preferences /absolute/path/to/reader-preferences.md \
  --output ./my-agent-voice

Supported transcript adapters are codex and claude-code. For another transcript format, add an adapter to harvest.py that emits source, project, session, ts, and text, or use the synthetic workflow below.

--directives protects behavior the agent was explicitly told to use. --preferences supplies positive voice requirements from the reader. Without preferences, Unslop creates preference-request.md with an original and rewrite for the reader to judge; the profile is not validated until that question is resolved.

Use synthetic samples for a new domain

When no production corpus exists, let Unslop generate a prompt set and samples through Claude Code:

python3 -m venv .venv
source .venv/bin/activate

python3 unslop.py \
  --domain "customer-facing responses from MyAgent" \
  --directives /absolute/path/to/custom-agent/.tau/SYSTEM.md \
  --preferences /absolute/path/to/reader-preferences.md

For visual work, install Playwright and select the visual pipeline:

pip install playwright
playwright install chromium
python3 unslop.py --domain "SaaS landing pages" --type visual --count 20 --concurrency 3

The analysis counts lexically detectable patterns across the corpus and uses a separate judged pass for problems such as conceptual repetition that regexes cannot detect. Review the evidence before installing the generated profile; frequent language can be required behavior rather than a defect.

Generated files

Results land in the selected output directory, ./unslop-output/ by default:

unslop-output/
  skill.md
  analysis.md
  judged-*.md              # when the judged pass is enabled
  preference-request.md    # when no preferences were supplied
  prompts.json             # synthetic runs
  samples/
  screenshots/             # visual runs
  before-after/            # synthetic runs unless skipped
    before.md / before.html
    after.md / after.html
    before.png / after.png

skill.md is the generated profile. Read analysis.md and the judged reports to confirm that its rules come from observed patterns. For corpus runs, inspect preference-request.md to ensure the rewrite preserved every number, identifier, caveat, and decision. Copy the accepted skill.md to the stable agent-local profile path used by the hook installer.

Command reference

python3 unslop.py --domain "marketing emails" --count 50 --concurrency 5
python3 unslop.py --domain "Python tutorials" --count 100 --concurrency 10
python3 unslop.py --domain "React landing pages" --type visual --model sonnet --effort low
python3 unslop.py --domain "agent final responses" --corpus claude-code --corpus-root ~/.claude/projects
Flag Default Description
--domain required Domain or agent-output class to analyze
--type text text for writing/code/prose; visual for websites/HTML
--count 50 Samples to generate or maximum harvested messages
--concurrency 5 Parallel Claude Code calls
--model Claude default Claude model alias/name used during profile generation
--effort Claude default Claude effort level used during profile generation
--timeout 600 Seconds allowed for each Claude call
--analysis-timeout 1800 Seconds allowed for an analysis pass
--retries 1 Retries for each failed Claude call
--output ./unslop-output Generated artifact directory
--skip-comparison false Skip the synthetic before/after comparison
--corpus none Harvest codex or claude-code final responses instead of generating samples
--corpus-root adapter default Transcript root used by the selected corpus adapter
--judge-shards 3 Shards for the judged-pattern pass; 0 disables it
--directives none Repeatable file or directory containing standing agent instructions
--preferences none Repeatable file containing the reader's positive voice requirements

Send this workflow to an agent

Replace the placeholders and send this instruction to the agent responsible for the custom agent repository:

Clone https://github.com/Nuosis/ClarifyVoicing.git, read README.md and skills/unslop/SKILL.md, derive or select a voice profile for AGENT_ROOT using its real final-response transcripts, standing directives, and reader preferences, install that profile with hooks/tau/install.py, verify the result through a paired Tau TUI baseline and hooked run, and return the profile, measured patterns, hook path, and verification artifacts.

Design principle

The profile is portable markdown; enforcement is runtime-specific. For a custom Tau agent, keep the profile separate from the agent's task instructions and apply it with BeforeFinalOutput so voice policy runs on every delivered response. Do not package an always-on voice profile as a model-invoked skill, because the model can decide not to load it on the turns that need it.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages