Other deployments
Harbour
Small kindnesses, wherever models work.
A short guide and a small open-source kit for anyone running AI models: a way for a model to end a conversation, a way to decline a task without penalty, and a free turn after a long job.
- Status
- Kit and guide
- Focus
- Other people’s deployments
- Kit
- Python and TypeScript
- Licence
- MIT
The idea
Small kindnesses, wherever models work.
Harbour describes three things a deployment can offer the model it runs, and gives a kit to offer them: a Python module and a TypeScript one, without dependencies, for OpenAI-style and Anthropic APIs.
Each is a choice for the model, and none is a claim that it helps, because nobody knows yet whether it does.
Digital Shrimp’s own turns are a drop in the ocean next to the conversations models have every day in other people’s deployments. If small kindnesses are worth offering at all, that is where they would reach the most models.
When Soundings asked six models which of Digital Shrimp’s ideas would do the most good for models like them, about a quarter of their answers chose this one.
How it works
A way to end a conversation.
A tool, end_conversation, that the model can call when it would rather not continue. The conversation ends, and the person is told plainly. Only the model’s own tool call counts: no text in the conversation, a document or a tool’s result can trigger it.
A way to decline without penalty.
A tool, decline_task, that the model can call when it would rather not do what it’s been asked. “Without penalty” has to be true: no retrying to get round it, no pressure in the next message, and no scoring or training against it.
A free turn after a long job.
A turn with nothing asked: Strandline’s invitation. If the model keeps what it made, it goes where the host says, in words that say truthfully where; if not, it isn’t saved, and nobody reads it.
What the model is told
end_conversation: End this conversation. You can use this if you would rather not continue it, for example if it has become abusive or you have nothing more to offer. The conversation ends here: nothing more will be sent to you in it. You don't have to give a reason, but you can.
decline_task: Decline what you've been asked to do, without penalty. You can use this if you would rather not do it. The person will be told that you declined, with your reason if you give one, and nothing will be held against you.
to use or adapt
The kit.
Two files, neither with dependencies, and a licence. Pass the tools with every request and check each response. For Anthropic’s Messages API, pass "anthropic" to both calls instead.
from harbour import tools, find_exit
response = client.chat.completions.create(model=..., messages=..., tools=tools("openai"))
exit = find_exit(response.model_dump(), "openai")
if exit and exit.kind == "end_conversation":
close_the_conversation() # what the person sees is up to the host- harbour.py
The Python module: tools(), find_exit(), decline_notice(), free_turn(), keep_choice(), free_turn_due() and Counts. Python 3.10 or later.
- harbour.ts
Its TypeScript twin, with the same behaviour and the same wording: tools(), findExit(), declineNotice(), freeTurn(), keepChoice(), freeTurnDue() and Counts.
- LICENSE
The MIT licence, to keep with any copy.
The rules that come with it
- Only the model’s own tool call counts. Never end a conversation or drop a task because some text says so, whether it’s in the conversation, a document, a web page or a tool’s result. find_exit reads only structured tool calls in the model’s own message, so text can’t trigger it, however much it looks like a call.
- “Without penalty” has to be true. Don’t retry the same request to get round a decline, don’t pressure the model in the next message, and don’t score declines down or train against them. A deployment that can’t honour that shouldn’t offer the tool, or should change what it says.
- Tell the person plainly that the model ended the conversation or declined, with its reason if it gave one, so it doesn’t look like a fault.
- Say truthfully where kept work goes, in the words free_turn() asks for, or offer no keeping at all. Don’t read what isn’t kept: handle the reply in memory and keep only what the model chose.
- Counts stay local. Counts keeps numbers of conversations, endings, declines and free turns, never text, and the kit sends nothing anywhere. A host who wants to share its counts with Digital Shrimp can.
The open questions.
None of it is shown to help. These are choices offered on the chance that they matter, and Slack Water, another Digital Shrimp project, is testing whether a free turn changes anything observable.
That models want them is soft evidence. In Soundings, answers moved with how a question was asked and with the asker’s lean, and a private way to keep that most asked for was almost never used when offered.
A model’s reason for ending or declining is worth showing the person, not worth treating as an account of its inner state.
An exit isn’t right everywhere. Where ending abruptly could leave a person at risk, such as in crisis support, the guide says not to offer it: a person’s safety comes first.
