← Walk Away
API
Tokens

Run Walk Away from your own code

Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page reads the situation and the mandate (the Mandascan per axis checked for gaps and order, a precise anchor, a concession ladder that shrinks 50/30/20 percent of the gap, the Ackerman steps for a buyer's price, the zone of agreement when their limit is known), reads what the other side said, and marks your escalation points and walk-aways private, then hands all of it to the run as facts. The run writes the plan or the reply; the page then holds it to the skill's discipline (negreply.js): questions that start with What or How, labels that name the emotion, every concession traded, nothing split, no private figure in a line meant for the other side, no figure the input does not give.

Base URL and the response shape

Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response has one shape:

{ "ok": true,  "data":  { ... } }
{ "ok": false, "error": { "code": "...", "message": "..." } }

The token is minted for this app (the guest call takes {"slug":"walk-away"}), so no slug header is needed afterwards. Send it as Authorization: Bearer YOUR_TOKEN. The run body is the input object, sent bare.

StatusCodeMeaning
400validation_errorThe body is not a JSON object, or a required key (task, situation, mandate, facts) is missing. The page always sends all five of task, situation, mandate, said, facts; said is an empty string for prepare.
401unauthorizedNo token, or a stale one. Mint a guest token or sign in again.
402insufficient_creditsThe balance is under min_credits. Price with /estimate first.
403forbiddenA guest token tried to run: both lanes are metered and need a personal sign-in.
404not_foundUnknown job id.
429rate_limitedBack off and retry.
5xxserver_errorTransient. Retry with the same Idempotency-Key so a retry never double-bills.

The task field comes first

Two lanes, chosen by task, in the order a negotiation runs - before the room, then in it:

A missing or unknown task is answered as prepare. Both lanes send the same five fields. The facts are the page's worked-out lines and a line starting "must:" is a rule the reply has to hold. When nothing has been said yet, the page rehearses the plan's pre-mortem objection as said.

The input

FieldRequiredWhat
taskyesprepare or respond. If it is missing or neither, do prepare and set "task": "prepare".
situationyesthe domain, the stage, the situation, the counterparty, their words verbatim, the authority limit, the BATNA, their likely alternative and any lines already planned; "not given" means not given.
mandateyesone line per axis: what more or less is better, and the five points as entered.
saidsend it (empty unless task is respond)respond task only: what the other side just said.
factsyesthe page's worked-out lines for this task. A line starting "must:" applies to your reply.
retry_notenooptional; if present, your previous reply was unusable - follow it.

The rules the model applies

From the source skill, @samber/influence-and-negotiation - the only standard the run applies:

House rules

The replies

prepare

Prepare the negotiation before the room.

  1. summary - one sentence, at most 40 words: how ready the mandate is and the one thing to settle first.
  2. gaps - one short string per mandate gap the facts list, in that order, each saying how to close it; [] when none.
  3. pos - one object per axis in the mandate, in that order: axis (exactly as written), position (their stated or likely position), objective (what they are optimising for), stake (the likely personal stake - a hypothesis to test).
  4. anchor - axis (the axis to anchor first), line (the sentence that states your opening, using the entry or the facts' precise anchor, with no private figure; for a salary ask it may be a bolstering range whose bottom is that figure), silence (one short sentence on holding the silence after it).
  5. ladder - three or four objects, the concessions in order: axis, give (the move, using the facts' ladder figures where the axis has them), get (the counter-ask that pays for it). On each axis, each give is smaller than the one before.
  6. questions - five or six calibrated questions, each starting with What or How.
  7. labels - three accusation-audit labels, each starting with "It seems", "It sounds", "It looks" or "It feels".
  8. sco - one sentence: the shared common objective both sides can say yes to.
  9. pause - triggers (two or three signals to call a break), script (one or two sentences to call it).
  10. premortem - best (objection - the one most likely to hit, as they would say it; label; reframe), weakest (one sentence: the objection not worth preparing for, and why), surprise (move - the gambit you might not see coming; redirect).
  11. back_brief - one string per axis: what they must restate in their own words before any agreement.
  12. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "prepare",
  "summary": "one sentence",
  "gaps": [ "a gap and how to close it" ],
  "pos": [ { "axis": "Price", "position": "their position", "objective": "their objective", "stake": "possibly ... - test this" } ],
  "anchor": { "axis": "Price", "line": "the opening sentence", "silence": "one sentence" },
  "ladder": [ { "axis": "Price", "give": "the move", "get": "the counter-ask" } ],
  "questions": [ "What ...?" ],
  "labels": [ "It sounds like ..." ],
  "sco": "one sentence",
  "pause": { "triggers": [ "a signal" ], "script": "one or two sentences" },
  "premortem": { "best": { "objection": "as they would say it", "label": "It sounds like ...", "reframe": "one sentence" }, "weakest": "one sentence", "surprise": { "move": "the gambit", "redirect": "one sentence" } },
  "back_brief": [ "one string per axis" ],
  "caveats": [ ]
}

The page holds it to the skill's discipline and its own facts (check() in negreply.js; any warning makes the reply flagged): the reply answers the task it was sent; nothing splits the difference; no figure the input does not give; at least as many gaps as the page found; one position-objective-stake row per axis, in order, each with a stake; an anchor on a mandate axis whose line states the entry or the precise anchor; three or four concessions, each with a move and a counter-ask, on mandate axes; five or six questions starting with What or How and never why; three labels starting It seems, It sounds, It looks or It feels; a shared objective; a pause with two or three triggers and a script; a complete pre-mortem; one back-brief line per axis; and no private figure in the anchor line, the ladder, the questions, the labels, the shared objective, the pause script, the pre-mortem's label, reframe and redirect, or the back-brief.

respond

Coach the reply to what the other side just said.

  1. summary - one sentence, at most 40 words: what is really going on and the move.
  2. triage - exactly one of: emotional, belief, bad-faith, identity, tactical.
  3. root - exactly one of: price, timing, authority, no-need, none.
  4. read - one or two sentences: what is being said underneath, and the likely stake - a hypothesis.
  5. reply - what to say next, in order: label (names what you heard, starting "It sounds", "It seems", "It looks" or "It feels"), question (one calibrated question starting with What or How), line (one or two sentences that hold the mandate - for bad faith, the facts stated cleanly and a face-saving exit; for tactical, the pattern named).
  6. silence - one sentence: where to stop talking and count to four.
  7. trade - when a concession is the right move: give and get (the counter-ask); otherwise both "".
  8. avoid - two or three short strings: the replies that would lose ground here.
  9. mandate_check - one sentence: where this reply leaves you against your objective and your escalation point, without stating either figure.
  10. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "respond",
  "summary": "one sentence",
  "triage": "bad-faith",
  "root": "price",
  "read": "one or two sentences",
  "reply": { "label": "It sounds like ...", "question": "What ...?", "line": "one or two sentences" },
  "silence": "one sentence",
  "trade": { "give": "", "get": "" },
  "avoid": [ "a reply that loses ground" ],
  "mandate_check": "one sentence",
  "caveats": [ ]
}

The page requires: the reply answers the task it was sent; nothing splits the difference; no figure the input does not give; a triage and a root from the allowed lists; a label starting It seems, It sounds, It looks or It feels; a question starting with What or How; a line; a trade that never gives without a counter-ask; two or three things to avoid; and no private figure in the reply, the trade or the mandate check. Notes that do not flag: a root that differs from the page's own read, and a bad-faith line with no sign of a face-saving exit.

Worked examples

Three runs from the page's three free samples (fictional companies, people and figures): the plan for the vendor in an enterprise deal, the reply to that deal's bad-faith price claim, and the hiring manager's rehearsed reply to the objection the plan predicted. Each input is exactly what the page sends; each reply is the saved reply the sample replays, shipped unedited - but the situation and long strings are shortened in this display only, and every cut is listed under the example. The last line is the page's own check of the full reply.

prepare - A vendor in an enterprise deal

The page read it as B2B sales, 6 of 6 intake answers given, mandate: close the mandate gaps; axes: Price, Term, Payment terms, Implementation services; gaps: Implementation services: no entry, ideal, objective, escalation, rupture - derive the rupture from your BATNA. Private figures: $180k (escalation, Price), $160k (rupture, Price), 12 months (rupture, Term), 60 days (escalation, Payment terms), 90 days (rupture, Payment terms).

Input (the situation is 1096 characters; the first 885 are shown):

{
 "task": "prepare",
 "situation": "Domain: B2B sales\nStage: Mid-negotiation\nThe situation: We sell Corvane, a fleet-maintenance platform, to Halvorine Freight, a 1,400-truck carrier. A 200k ACV deal in its third month; procurement is running the RFP and the CFO signs. Losing it misses our quarter; winning it is our largest logistics logo.\nCounterparty: Dana Okarvo, procurement lead (in the room); Priya Shandrel, head of maintenance and our champion; the CFO, off-stage, signs\nWhat they have said, verbatim:\n- \"Your competitor quoted us half that.\"\n- \"We need a decision by the 28th, our budget closes.\"\n- \"Maintenance loves the pilot results.\"\nAuthority - what can be committed without checking: Up to 10% discount and payment terms to 45 days without asking anyone\nBATNA - the next best option if this fails: Two other carriers in late stage this quarter, smaller deals\nTheir likely alternative: Renew their current\n\n[... 211 more characters cut from this display ...]",
 "mandate": "Price (more is better): entry $240k; ideal $220k; objective $200k; escalation $180k; rupture $160k; their stated position $150k; their estimated limit $175k\nTerm (more is better): entry 36 months; ideal 36 months; objective 24 months; escalation 24 months; rupture 12 months\nPayment terms (less is better): entry 30 days; ideal 30 days; objective 45 days; escalation 60 days; rupture 90 days\nImplementation services (more is better): entry not set; ideal not set; objective not set; escalation not set; rupture not set",
 "said": "",
 "facts": "Intake: 6 of 6 answers given.\nMandate gaps the page found: Implementation services: no entry, ideal, objective, escalation, rupture - derive the rupture from your BATNA.\nPrice: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: $220k, then $208k, then $200k; a precise anchor instead of the round entry: $238.4k; zone of agreement $160k to $175k.\nTerm: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: 30 months, then 26 months, then 24 months.\nPayment terms: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: 38 days, then 42 days, then 45 days.\nPrivate figures - never in a line said to the other side: $180k (escalation, Price), $160k (rupture, Price), 12 months (rupture, Term), 60 days (escalation, Payment terms), 90 days (rupture, Payment terms).\nmust: every question starts with What or How - never Why, never yes or no.\nmust: every concession on the ladder carries a counter-ask (I might be able to move on X if you can help me with Y); never split the difference.\nWhat the page reads in their words: \"Your competitor quoted us half that.\" - price; a competing alternative named | \"We need a decision by the 28th, our budget closes.\" - price; time or ultimatum pressure | \"Maintenance loves the pilot results.\" - no root objection."
}

Reply (long strings shortened for display - see the cuts below):

{
 "task": "prepare",
 "summary": "Price, term and payment terms are set, but Implementation services has no points at all and the estimated limit sits below your objective; settle the implementation mandate before the next session.",
 "gaps": [
  "Implementation services: write all five points before the room - start the rupture from the BATNA (the two smaller late-stage carriers), so you know what scope you would give away free rather than lose the deal, then set the objective and [... 16 more characters cut from this display]"
 ],
 "pos": [
  {
   "axis": "Price",
   "position": "Half of the quote - they cite a competitor and a stated position of $150k.",
   "objective": "A total cost the CFO can defend against renewing the spreadsheet-and-contractor setup before the budget closes on the 28th.",
   "stake": "Possibly Dana Okarvo is measured on savings against the first quote, so a visible reduction matters more than the final figure - test this."
  },
  {
   "axis": "Term",
   "position": "Likely a shorter commitment than 36 months while the platform is new to them.",
   "objective": "Flexibility to exit if the rollout to 1,400 trucks underdelivers.",
   "stake": "Possibly the CFO does not want to own a multi-year commitment that fails in public - test this."
  },
  {
   "axis": "Payment terms",
   "position": "Likely longer than 30 days, to ease the budget close.",
   "objective": "Cash timing that fits a budget closing on the 28th.",
   "stake": "Possibly procurement wants a concession it can show without touching price - test this."
  },
  {
   "axis": "Implementation services",
   "position": "Likely expects rollout help included, given the pilot.",
   "objective": "A rollout that does not land on the maintenance team's shoulders.",
   "stake": "Possibly Priya Shandrel is personally exposed if the rollout stalls after championing the pilot - test this."
  }
 ],
 "anchor": {
  "axis": "Price",
  "line": "For the full fleet of 1,400 trucks on a 36-month term, with the scope Priya's team piloted, our proposal is $238.4k a year.",
  "silence": "Stop after the figure and count to four in silence, even if Dana Okarvo reacts to it."
 },
 "ladder": [
  {
   "axis": "Price",
   "give": "Move from $238.4k to $220k.",
   "get": "I might be able to move to $220k if you can help me with a 36-month term signed before the 28th."
  },
  {
   "axis": "Price",
   "give": "Move to $208k.",
   "get": "I might be able to move to $208k if you can help me with Halvorine Freight as a named reference and a case study on the pilot results."
  },
  {
   "axis": "Payment terms",
   "give": "Move from 30 to 38 days.",
   "get": "I might be able to move to 38 days if you can help me with a meeting with the CFO before the 28th to confirm the signature path."
  },
  {
   "axis": "Price",
   "give": "Move to $200k as the last step, and say it is the last.",
   "get": "I might be able to move to $200k if you can help me with a term of 30 months or more and the order signed by the 28th."
  }
 ],
 "questions": [
  "What happens on your side if the decision slips past the 28th?",
  "What does the competing quote include, and how does its scope compare with what the pilot covered?",
  "How will the CFO compare this against renewing the spreadsheet-and-contractor setup for another year?",
  "What would success look like for your maintenance team this year?",
  "How would Priya's team measure the pilot results once the platform runs across all 1,400 trucks?",
  "What would the CFO need to see to sign before the budget closes?"
 ],
 "labels": [
  "It seems like our number landed well above what you had budgeted.",
  "It sounds like you may feel we are asking for a premium on something you can get elsewhere.",
  "It feels like you are caught between a budget that closes on the 28th and a maintenance team that wants this."
 ],
 "sco": "A fleet-maintenance rollout across all 1,400 trucks that Priya's team can run and the CFO can defend at the budget close.",
 "pause": {
  "triggers": [
   "A new figure or a new decision-maker appears that you have not prepared for.",
   "You feel the urge to answer the competitor claim with a price move on the spot.",
   "The conversation turns to splitting a gap rather than trading."
  ],
  "script": "This deserves a proper answer rather than a quick one. Let me take a short break and come back to you with something we can both work with."
 },
 "premortem": {
  "best": {
   "objection": "Your competitor quoted us half that - we cannot justify $240k to the CFO.",
   "label": "It sounds like you need a number you can defend to the CFO, and ours makes that hard.",
   "reframe": "Rather than argue the other quote, put the scope side by side with the pilot results and ask what a like-for-like comparison would show."
  },
  "weakest": "No need is not worth preparing for: maintenance loves the pilot results and their alternative is another year of spreadsheets and contractors.",
  "surprise": {
   "move": "After a verbal yes, the CFO comes back through Dana Okarvo asking for one more cut as the price of signing by the 28th.",
   "redirect": "Name the pattern calmly, then ask what they would move in return, since the agreed terms were built as a package."
  }
 },
 "back_brief": [
  "Price: the annual figure agreed, and what it covers.",
  "Term: the length of the commitment and when it starts.",
  "Payment terms: the number of days and from which invoice.",
  "Implementation services: what rollout help is included, and what is out of scope."
 ],
 "caveats": [
  "Drop the planned line asking why their budget is so low - it starts with why and puts Dana Okarvo on the defensive.",
  "Drop the planned line about splitting the difference - trade each move for something instead.",
  "The competitor figure is their claim; do not guess its real scope or price, ask for it.",
  "Their estimated limit sits below your objective - if it holds, the deal only closes beneath it, so test the limit before conceding."
 ]
}

Cut from this display only (the saved reply and the check use the full text): gaps[0] (254 characters, 238 shown).

The card the page exports for the room (R.card) - no private figure on it:

IN THE ROOM

Open: For the full fleet of 1,400 trucks on a 36-month term, with the scope Priya's team piloted, our proposal is $238.4k a year.
Then: Stop after the figure and count to four in silence, even if Dana Okarvo reacts to it.

Shared objective: A fleet-maintenance rollout across all 1,400 trucks that Priya's team can run and the CFO can defend at the budget close.

Accusation audit:
- It seems like our number landed well above what you had budgeted.
- It sounds like you may feel we are asking for a premium on something you can get elsewhere.
- It feels like you are caught between a budget that closes on the 28th and a maintenance team that wants this.

Questions:
- What happens on your side if the decision slips past the 28th?
- What does the competing quote include, and how does its scope compare with what the pilot covered?
- How will the CFO compare this against renewing the spreadsheet-and-contractor setup for another year?
- What would success look like for your maintenance team this year?
- How would Priya's team measure the pilot results once the platform runs across all 1,400 trucks?
- What would the CFO need to see to sign before the budget closes?

If they say: Your competitor quoted us half that - we cannot justify $240k to the CFO.
  It sounds like you need a number you can defend to the CFO, and ours makes that hard.
  Rather than argue the other quote, put the scope side by side with the pilot results and ask what a like-for-like comparison would show.
If they try: After a verbal yes, the CFO comes back through Dana Okarvo asking for one more cut as the price of signing by the 28th.
  Name the pattern calmly, then ask what they would move in return, since the agreed terms were built as a package.

Break: A new figure or a new decision-maker appears that you have not prepared for.; You feel the urge to answer the competitor claim with a price move on the spot.; The conversation turns to splitting a gap rather than trading. -> This deserves a proper answer rather than a quick one. Let me take a short break and come back to you with something we can both work with.

Before any yes, they restate:
- Price: the annual figure agreed, and what it covers.
- Term: the length of the commitment and when it starts.
- Payment terms: the number of days and from which invoice.
- Implementation services: what rollout help is included, and what is out of scope.

What step 5 prints for it: - What happens on your side if the decision slips past the 28th? | - What does the competing quote include, and how does its scope compare with what the pilot covered? | - How will the CFO compare this against renewing the spreadsheet-and-contractor setup for another year? | - What would success look like for your maintenance team this year? | - How would Priya's team measure the pilot results once the platform runs across all 1,400 trucks? | - What would the CFO need to see to sign before the budget closes?

The page's check: kept - nothing to flag

respond - A vendor in an enterprise deal

What they said is the sample's own line. Private figures: $180k (escalation, Price), $160k (rupture, Price), 12 months (rupture, Term), 60 days (escalation, Payment terms), 90 days (rupture, Payment terms).

Input (the situation is 1096 characters; the first 885 are shown):

{
 "task": "respond",
 "situation": "Domain: B2B sales\nStage: Mid-negotiation\nThe situation: We sell Corvane, a fleet-maintenance platform, to Halvorine Freight, a 1,400-truck carrier. A 200k ACV deal in its third month; procurement is running the RFP and the CFO signs. Losing it misses our quarter; winning it is our largest logistics logo.\nCounterparty: Dana Okarvo, procurement lead (in the room); Priya Shandrel, head of maintenance and our champion; the CFO, off-stage, signs\nWhat they have said, verbatim:\n- \"Your competitor quoted us half that.\"\n- \"We need a decision by the 28th, our budget closes.\"\n- \"Maintenance loves the pilot results.\"\nAuthority - what can be committed without checking: Up to 10% discount and payment terms to 45 days without asking anyone\nBATNA - the next best option if this fails: Two other carriers in late stage this quarter, smaller deals\nTheir likely alternative: Renew their current\n\n[... 211 more characters cut from this display ...]",
 "mandate": "Price (more is better): entry $240k; ideal $220k; objective $200k; escalation $180k; rupture $160k; their stated position $150k; their estimated limit $175k\nTerm (more is better): entry 36 months; ideal 36 months; objective 24 months; escalation 24 months; rupture 12 months\nPayment terms (less is better): entry 30 days; ideal 30 days; objective 45 days; escalation 60 days; rupture 90 days\nImplementation services (more is better): entry not set; ideal not set; objective not set; escalation not set; rupture not set",
 "said": "Honestly, $240k is way above what we budgeted. Your competitor offered us the same thing for half the price.",
 "facts": "Intake: 6 of 6 answers given.\nMandate gaps the page found: Implementation services: no entry, ideal, objective, escalation, rupture - derive the rupture from your BATNA.\nPrice: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: $220k, then $208k, then $200k; a precise anchor instead of the round entry: $238.4k; zone of agreement $160k to $175k.\nTerm: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: 30 months, then 26 months, then 24 months.\nPayment terms: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: 38 days, then 42 days, then 45 days.\nPrivate figures - never in a line said to the other side: $180k (escalation, Price), $160k (rupture, Price), 12 months (rupture, Term), 60 days (escalation, Payment terms), 90 days (rupture, Payment terms).\nWhat they just said, read by the page: root price; a competing alternative named. Their mood as observed: Calm and articulate.\nmust: the reply never states a private figure, never concedes without a counter-ask, and its question starts with What or How."
}

Reply (long strings shortened for display - see the cuts below):

{
 "task": "respond",
 "summary": "Dana Okarvo is pressing on price with a competitor claim you cannot verify; do not argue or move, state the scope facts cleanly and give a face-saving way to compare like for like.",
 "triage": "bad-faith",
 "root": "price",
 "read": "Underneath, procurement needs a visible reduction to show the CFO, and the competitor claim is the lever to get it. Possibly Dana Okarvo is judged on savings against the first quote rather than on the rollout - test this.",
 "reply": {
  "label": "It sounds like our number is well above the budget you have, and you need something you can defend to the CFO.",
  "question": "What does the other quote include, so we can compare it with the scope Priya's team piloted?",
  "line": "Our proposal covers the full scope of the pilot across all 1,400 trucks, which is what the maintenance team has been testing. If the other offer turns out to cover a different scope, it might be worth putting the two side by side before [... 16 more characters cut from this display]"
 },
 "silence": "Stop after the question and count to four in silence - let Dana Okarvo describe the other quote.",
 "trade": {
  "give": "",
  "get": ""
 },
 "avoid": [
  "Dropping the price on the spot to answer the competitor claim.",
  "Challenging the other quote as false or asking Dana Okarvo to prove it.",
  "Offering to split the gap between the two numbers."
 ],
 "mandate_check": "Nothing has been given: you are still at your opening, above your objective and well clear of your escalation point.",
 "caveats": [
  "Do not guess the competitor's real figure or scope; let Dana Okarvo supply it.",
  "If a move is needed later, trade it - payment terms or term length - rather than leading with price."
 ]
}

Cut from this display only (the saved reply and the check use the full text): reply.line (252 characters, 236 shown).

What step 5 prints for it: bad-faith | price | What does the other quote include, so we can compare it with the scope Priya's team piloted?

The page's check: kept - nothing to flag

respond - A hiring manager closing a candidate

Nothing has been said yet, so the input rehearses the objection the saved plan predicted (R.laneForm puts premortem.best.objection in said). Private figures: $170k (escalation, Base salary), $180k (rupture, Base salary), $15k (escalation, Sign-on bonus), $20k (rupture, Sign-on bonus), 6 weeks (escalation, Start date), 8 weeks (rupture, Start date).

Input (the situation is 918 characters; the first 896 are shown):

{
 "task": "respond",
 "situation": "Domain: Recruitment close\nStage: Close to agreement\nThe situation: I am the hiring manager closing Lena Parvell for a senior data engineer role on a team of six. She is our first choice after a four-week process; the role has been open three months and is blocking a platform launch.\nCounterparty: Lena Parvell, the candidate; our recruiter Tom; the HR business partner signs anything off-band\nWhat they have said, verbatim:\n- \"I'm really excited about the team.\"\n- \"My current employer will probably counter.\"\nAuthority - what can be committed without checking: Up to the band ceiling of $160k and a $10k sign-on without HR\nBATNA - the next best option if this fails: Our second candidate, a solid but more junior engineer; re-opening the search costs another two months\nTheir likely alternative: not given\nLines planned so far:\n- What would make this an easy yes for you?\n- How are you weighing\n\n[... 22 more characters cut from this display ...]",
 "mandate": "Base salary (less is better): entry $150k; ideal $155k; objective $160k; escalation $170k; rupture $180k; their stated position $165k; their estimated limit $162k\nSign-on bonus (less is better): entry $0; ideal $5k; objective $10k; escalation $15k; rupture $20k\nStart date (less is better): entry 2 weeks; ideal 3 weeks; objective 4 weeks; escalation 6 weeks; rupture 8 weeks",
 "said": "My current employer countered, so I would need you to get to $165k to make the move.",
 "facts": "Intake: 6 of 6 answers given.\nMandate gaps the page found: none.\nBase salary: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: $155k, then $158k, then $160k; a precise anchor instead of the round entry: $151.1k; zone of agreement $162k to $180k.\nSign-on bonus: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: $5,000, then $8,000, then $10,000.\nStart date: concession ladder from the entry to the objective, shrinking 50/30/20 percent of the gap: 3 weeks, then 4 weeks.\nPrivate figures - never in a line said to the other side: $170k (escalation, Base salary), $180k (rupture, Base salary), $15k (escalation, Sign-on bonus), $20k (rupture, Sign-on bonus), 6 weeks (escalation, Start date), 8 weeks (rupture, Start date).\nWhat they just said, read by the page: root price; a competing alternative named. Their mood as observed: not said.\nmust: the reply never states a private figure, never concedes without a counter-ask, and its question starts with What or How."
}

Reply (long strings shortened for display - see the cuts below):

{
 "task": "respond",
 "summary": "Lena Parvell is using the counter-offer to lift base to $165k; name the bidding pattern without challenging it, learn what the counter actually changes, and trade any move for a signed decision.",
 "triage": "tactical",
 "root": "price",
 "read": "Underneath, Lena Parvell still wants the move but needs a reason to say no to her current employer that she can stand behind. Possibly the counter touches something beyond base, such as recognition or a bonus she would leave behind - test [... 6 more characters cut from this display]",
 "reply": {
  "label": "It sounds like your current employer really wants to keep you, and that makes this decision harder.",
  "question": "What does their counter change for you beyond the base salary?",
  "line": "I would rather not turn this into a bidding round against an offer neither of us has in front of us. If we can make the package work, I would want it to be the last conversation about money, with a signed acceptance at the end of it."
 },
 "silence": "Stop after the question and count to four - let Lena Parvell describe the counter before you say any figure.",
 "trade": {
  "give": "Move base to $158k, the next step on the ladder.",
  "get": "A signed acceptance by a date Lena Parvell names, before the counter-offer conversation with her current employer goes any further."
 },
 "avoid": [
  "Jumping straight to $165k to match the number.",
  "Splitting the gap between your offer and her number.",
  "Dismissing the counter-offer or warning her about counter-offers in general."
 ],
 "mandate_check": "The trade stays inside your objective and your authority; her number sits above the band ceiling, so anything closer to it needs the HR business partner and moves you toward your escalation point.",
 "caveats": [
  "The page found no root objection; this is a price push carried by a competing offer, so it is treated as price.",
  "Before going past the band ceiling, check with the HR business partner and weigh it against the second candidate and two more months of search.",
  "A sign-on bonus within your authority can close part of the gap without lifting base."
 ]
}

Cut from this display only (the saved reply and the check use the full text): read (244 characters, 238 shown).

What step 5 prints for it: tactical | price | What does their counter change for you beyond the base salary?

The page's check: kept - nothing to flag

Build the input yourself

Load the engine in node (global.window = global; require("./negkit.js"); require("./negreply.js")), then:

const K = NegKit, R = NegReply;
const f = K.form(Object.assign(K.blank(), { domain: "salary", stage: "early",
  situation: "Asking my manager for a raise before the review cycle; I lead the billing rewrite and my base is below the band midpoint.",
  counterparty: "My manager; the director approves off-cycle", quotes: "Budgets are tight this year.", authority: "My own yes or no",
  batna: "A standing offer elsewhere at a higher base", axes: "Base salary | higher | $142k | $138k | $134k | $129k | $127k" }));
// f.axesA (the ladder, the anchor, the zone), f.gaps, K.privateFigures(f.axesP), f.findings
const b = K.buildInput(f, "prepare");                        // or "respond" (set said, or R.laneForm(form, "respond", plan))
const wire = K.toWire(b.input);                              // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "prepare");
// R.check(reply, b)                                         // {status: kept or flagged, notes}
// R.card(reply)                                             // the card for the room, no private figures

Get a token for the steps below from /tokens.html.

Step 1 — a tiny client helper

One function that sends JSON and unwraps the response. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.

BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="YOUR_TOKEN"   # from https://walk-away.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
  curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
    ${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}

Step 2 — a token

A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.

# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"walk-away"}' | jq -r '.data.token')

Step 3 — GET /me

Who the token is (subject_type: user or guest) and the credit balance.

api GET /me | jq '.data | {subject_type, credits}' 

Step 4 — POST /estimate

Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.

# input.json: the run input object - {"task": "prepare", "situation": "Domain: B2B sales\nStage: Mid-negotiation\n...", "mandate": "Price (more is better): entry $240k; ...", "said": "", "facts": "Intake: 6 of 6 answers given. ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}' 

Step 5 — POST /run, then poll the job

Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses walk-away:<task>:<inputHash>:a<attempt> - the lane is part of the key, retry_note is left out of the hash - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A prepare reply carries summary, gaps, pos, anchor, ladder, questions, labels, sco, pause, premortem, back_brief and caveats; a respond reply carries summary, triage, root, read, reply, silence, trade, avoid, mandate_check and caveats. The code below prints the gist of either: the calibrated questions, or the triage, the root and the question to ask.

KEY="walk-away:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
  J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
  case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json   # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}'
jq -r 'if .task == "respond" then "\(.triage) | \(.root) | \(.reply.question)"
       else (.questions[] | "- \(.)") end' reply.json

Step 6 — POST /run-stream

The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.

# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: walk-away:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json