A thread records what a team said, not what it decided.
A distributed team can generate a long, engaged discussion and still not converge, because the thread format rewards whoever answers first and whoever answers loudest. The constraint that actually governs the decision often belongs to the person who has not replied yet. By the time they do, the discussion has already organized itself around a different question.
I built Ringi to give those positions a structure before they collide. It operates inside Slack, where the decision is already being discussed: it gathers individual positions, identifies the crux, writes a brief, and returns the recommendation to the people the decision affects.
The system behind the conversation
Ringi separates the conversation from the decision state. A typed state machine governs the session while the gathering and synthesis passes handle the language. That separation is the central design commitment of the project, and it exists for a specific reason: an eloquent model response should never be sufficient to move a session into a state the participants have not actually reached.
The implementation covers multi-workspace OAuth installation, direct stakeholder messaging, reminders, a PostgreSQL database through Drizzle, and Langfuse instrumentation for model cost, latency, and output quality. I also built model evaluations and fixtures for assessing synthesis quality, because a synthesis pass that degrades quietly is worse than one that fails loudly.
Gather before converging
Each stakeholder receives a direct message and answers independently, without visibility into the other responses. This captures the constraint underneath a position rather than a reaction to whoever posted first, which is the information a thread structurally destroys.
Make the disagreement explicit
The synthesis pass separates the disagreement from the discussion surrounding it and states the crux as a single contested question with its options attached. The test I hold the output to is narrow: a participant should recognize their own concern in the brief, and should be able to determine what the recommendation would change if adopted.
Give objections a path
An objection opens a revision round rather than a new thread. The decision record retains agreement explicitly, including who agreed and what remained contested, so the artifact that survives the session describes the decision rather than the conversation that produced it.
What I owned
I designed the product and built the conversation state machine, the Slack integration, the database layer, and the deployment. The most demanding boundary in the project sits between flexible natural language and explicit application state: the conversation is permitted to vary, but the transitions between states still require rules that the model cannot talk its way past.
A deliberate tradeoff
Ringi keeps the decision with the participants rather than producing a summary and declaring the matter resolved. This makes the interaction more involved than a single generated digest, and it costs the participants time that a summary would not. The return is that the resulting record carries the context of who agreed and what stayed contested, which is the part a summary discards and the part a team needs six weeks later.
Where it stands
Ringi is in early access. The public site includes a theater replay, and the implementation supports the end-to-end decision loop. I am not claiming measured adoption or time savings, because I do not have them: the open question is how the workflow holds up when teams run it against their own decisions rather than my test fixtures.