Agent scorecards

The phone pushes each rep’s rollups to MADDOX on a key that can only write that rep’s numbers, and a partial batch failure fails only its own rows.

Scorecards

Numbers a rep can be shown without an argument.

Call rollups are computed by the phone and pushed into MADDOX, where they join the rest of a rep’s scorecard. A bound key can only write its own agent’s numbers — there is no arrangement in which one rep’s integration writes another rep’s performance — and a batch push is partial-failure by design, so one bad row does not discard nineteen good ones.

How it works

Bound keys and partial batches

Two design choices, both of which only matter on a bad day.

The key is bound

A scorecard key is issued against one agent and can write that agent’s numbers only. Binding is enforced by rejection rather than correction: an item naming a different agent is refused and reported, not quietly rewritten to the bound identity. That distinction matters on a batch — coercion would let twenty differently-identified rows collapse into one agent’s numbers without anybody noticing.

The batch is partial, and safe to replay

A push carrying twenty rollups where one is malformed writes the nineteen and reports the one; there is no wrapping transaction, so one item’s failure can never roll back another’s. Re-sending is safe: a rollup is keyed on the agent and the period it covers, so a replayed push updates that window in place and never duplicates it. The response says which rows were created and which were updated, so an ops team recovering a lost day can tell what actually happened.

The scorecard composes

Call numbers sit alongside the rest of a rep’s scorecard rather than in a separate phone report. Around thirteen figures arrive per period — calls, connects, appointments set, callbacks scheduled, flagged calls, talk time, connect and set rates, QA and adherence and sentiment averages, dials per hour, talk-listen ratio — plus a nested objections breakdown. A metric that cannot be measured is shown as not measurable rather than as a zero, because those are different facts.

In the product

Call performance, inside the scorecard.

The BDR and campaign call-intelligence dashboard in MADDOX: dials 5,310, connects 1,705, decision-makers reached 316, meetings booked 21, average QA score 15.9 of 100 and objections overcome 3.9 percent, with an objection breakdown and a script-and-QA rubric-criteria panel.
rollups_in_batch: 20 written: 19 rejected_and_reported: 1 Sample data — illustrative product UI, not a performance claim.

The mechanism

Three decisions that only matter on a bad day

Ingestion code is judged on what it does when something is already wrong: a malformed row, a replayed batch, a key that is not what it claims. All three cases have an answer here, and none of the answers is to guess.

A bound key is refused, not corrected

Where a key is issued against one agent, an item naming a different agent is rejected and reported as forbidden. It is not quietly rewritten to the bound identity, and the difference is the entire point on a batch. Coercion would let twenty differently-identified rollups collapse into one agent’s numbers, and the push would return success for all twenty. Nobody would ever find that by reading a report.

This is stricter than the call-results path, which does coerce a single call to the bound identity — one call, one identity, no ambiguity to hide. A batch is a different shape of risk and gets a different rule.

A replay updates in place and says so

A rollup is identified by the tenant, the agent, the period type and the period start. Re-sending the same window updates that row rather than adding a second copy of it, so an ops team recovering a lost day can simply push the day again. The response distinguishes what was created from what was updated, which is the part that makes the guarantee usable: a replay that reported only “success” would leave you unable to tell a re-push from a double-count without going and looking.

Partial by construction, with no wrapping transaction

Each item is independent. A push carrying twenty rollups where one is malformed writes the nineteen and reports the one, and there is deliberately no transaction around the batch, because one item’s failure must never roll back another item’s write. A well-formed envelope therefore always returns success at the HTTP level, and the outcome lives in a summary and a per-item result list instead.

The counts are arranged so they cannot quietly disagree: the number received always equals created plus updated plus failed, because every item takes exactly one outcome. A batch where those do not add up is a bug you can see rather than a number you have to trust.

Which reader owns a call score is a fact, not a fallback

Two producers write call outcomes in two different shapes — the live softphone at the root of the record, the historical assessment worker under its own namespace with different key names for the same concepts. The tempting repair is to try one and fall back to the other. That is exactly how the original defect survived a whole pilot: reading the wrong shape yields nulls, and nulls are indistinguishable from a call nobody ever scored.

So provenance is recorded on the call itself and decides the reader. A row whose shape and provenance disagree surfaces as visibly empty output on a call you know came from a given producer — which is a bug somebody notices — rather than being papered over for both. An unrecognized source falls to the live reader, which is what every pre-existing row is, so a new importer that forgets to register degrades to today’s behavior rather than to a blank screen.

Who it is for

For managers who have to justify a number

A performance conversation goes badly the moment the rep can argue with the arithmetic instead of the behavior.

  • Managers running one-on-ones off call activity.
  • Team leads who need per-rep numbers that nobody can contest.
  • Ops teams who have lost a day of data to one malformed row.

Questions

The things people actually ask.

Can one rep’s key write another rep’s numbers?

No. A scorecard key is bound to a single agent server-side. This is enforced where the write happens rather than trusted to the client, which is the only version of that guarantee worth having.

What happens to a batch with one bad row?

The good rows are written and the bad row is reported. Discarding a whole batch for one malformed entry means a single formatting error can cost a team a day of numbers.

What if a metric cannot be measured?

It is shown as not measurable rather than as zero. A rep whose zero turns out to mean no data will never trust the scorecard again, and they would be right not to.

We lost a day of pushes. Can we just send them again?

Yes. A rollup is identified by the agent and the window it covers, so replaying a batch rewrites those windows rather than adding a second copy of them. This is the one design decision on this page that only ever matters on a bad day, which is exactly why it was worth making.

How does the CRM know which shape a call score is in?

It looks up who wrote the row rather than guessing at its shape. Two producers write call outcomes in two different layouts — the live softphone and the historical assessment worker — and reading the wrong one produces nulls, which look identical to a call nobody ever scored. So provenance is recorded on the call and decides the reader. A row whose shape and provenance disagree shows up as visibly empty for a known producer instead of being quietly papered over for both.

Show a rep their own numbers.

If the first thirty seconds are about whether the number is right, the number is not doing its job.