Meetings
An agenda before and notes during — and the action items become issues on the project's board.
That last part is the reason this belongs in a tracker rather than beside one. A decision that produced work produces a row somebody is accountable for, and it shows up in the workload report, on the Gantt and in a timesheet without meetings knowing any of those exist.
Off by default. Administration → Workspace → Features turns it on per workspace,
and FELAGI_MEETINGS=false removes it from the installation entirely — a per-team
switch that could override an installation-wide one would not be a kill switch.
Scheduling
A meeting belongs to a project, never to a workspace alone. Without one there is no answer to "which of these matter to me", and a tracker with forty projects grows one undifferentiated list of every meeting anybody held.
All day
A workshop, an offsite, a course. Turn on All day and the form stops asking for a start time and a length, because neither is the answer to when it is.
Underneath it is stored like any other meeting: it begins at midnight and lasts a day.
That is deliberate — the calendar, the overlap check and the .ics need to know nothing
about all-day meetings to place one correctly. Only the wording changes, and it changes
in one place, so a screen added next year says the same as the two that exist now.
Saving a meeting sends nothing. Invitations go out when you send them, because a typo in a title should not already be an email everybody has.
The invitation
An .ics attachment, which is what makes it an invitation rather than an email about
a meeting. Without one every recipient copies a time into their own calendar by hand
and one of them gets it wrong.
Two details matter and are easy to get wrong:
- The identifier is stable for the life of the meeting, and derived from the ULID rather than the row id — so an installation restored into a new database keeps its calendar entries instead of issuing duplicates of every meeting.
- A sequence number rises with each change, which is what makes a second email an update to the entry already in somebody's calendar rather than a second entry beside it. A duplicate is how somebody ends up in the wrong room.
Cancelling sends METHOD:CANCEL, so the entry disappears from a calendar instead of
sitting there looking valid.
Changing who is coming
Add someone under the attendee list, at any time. Only members who are not already on it are offered — adding somebody twice is a duplicate row and a second invitation, and the way to prevent that is not to offer the option.
Nothing is sent when you add somebody. Adding a person and telling them are separate acts, as they are when the meeting is created: an organiser building a list over a minute should not be sending an email per click. If the invitation has already gone out, the message after adding says so.
Remove takes somebody off, and that is how "not coming" is said. There are no replies to give: being on the list is the answer, so somebody who cannot make it comes off it.
The list of meetings shows a count of who is coming, for the same reason: with no replies to tally there is one number worth showing, and it is the length of the list.
One action instead of four states, and it reads the same from across the room. What it gives up is the trace of having been asked — a declined attendee said no on the record, where a removed one was simply never there. For a team that sits together that was a distinction nobody was using.
Nobody is invited twice. An organiser adding a seventh person a week later notifies that person and not the six who had the invitation already, read from when each joined the list.
Repeating
Pick an interval when scheduling and Félagi keeps the next few occurrences in
existence, topped up daily by felagi:meetings.
Generated, not extended. The same reason cycles are: a series somebody has to remember to extend lapses in March, and nobody notices until the sync is not in a calendar.
The pattern is kept apart from the occurrences, and that separation is the point. Conflating them is what makes every calendar application confusing — edit one Tuesday and you are asked whether you meant all Tuesdays, because the Tuesday you clicked is both an event and a description of every event. Here a meeting is always one meeting: edit it, rename it, move it, cancel it, and the series carries on producing the ones after it.
Some consequences worth knowing:
- Attendees are inherited from the newest occurrence. Add somebody to next week's sync and they are on it from then on; remove them and they stop. A separate attendee list on the pattern would be a second copy of the truth, and the copy that drifts is the one nobody opens.
- The agenda is not carried forward. A standing agenda that repeats is one nobody reads by the fourth week, and an agenda copied from last time describes a meeting that already happened.
- The next slot follows the last occurrence, not today. Counting from today would drift: a fortnightly series topped up on an off-week would move to the other week and stay there.
- Nothing is backfilled. A series created today does not invent the Wednesdays it would have had last year.
Changing the schedule
Edit the schedule changes the pattern itself: the day, the time, the interval, how long it runs, how far ahead it generates. The series was writable once, at creation, and never again — so moving a weekly sync to Tuesdays meant stopping it and building a new one, which loses the history along with the pattern.
What happens to the occurrences already generated is the interesting half, and the answer is the one Stop repeating already gave: an untouched future occurrence is a plan and follows the new schedule; anything with notes, circulated or cancelled is the record of a meeting people are coming to, and stays exactly where it is. One rule, asked in both places.
A rescheduled series generates from the pattern, not from where it had got to. Worth saying because the alternative looks like nothing happening: the next slot normally follows the last occurrence, so a series moved to Tuesdays would have gone on producing Mondays for ever.
Past occurrences are never touched. Tuesday from now on does not make last Monday a Tuesday.
Stop repeating ends it. Scheduled occurrences with nothing written on them are removed; anything with notes stays, circulated or not, because that is the record of a meeting that happened rather than a plan. If the occurrence you were looking at was one of the empty ones, you land back on the list — sparing the one you happened to open would make the rule depend on where you clicked from.
Changing one
Edit is available to the organiser, and to anybody who can manage members. Title, location, when, all-day, and the agenda.
Two things are worth knowing before you use it.
It changes this occurrence only. A meeting in a series does not ask whether you meant every Tuesday, because that question has no safe default — the form says so where you can see it rather than in this guide.
Félagi cannot move an entry in somebody's calendar. Changing the time here changes it here. What updates a calendar is a second invitation, which arrives as an update to the entry they already hold rather than a duplicate beside it, because the sequence number rises with each change. If the invitation has already gone out, the form says so and the toast repeats it — and nothing is sent unless you send it, for the same reason nothing is sent when a meeting is created.
A cancelled meeting cannot be edited. It is the record of a meeting that will not happen, and editing it would produce a tidy-looking entry for an event nobody is going to.
Hours spent in the room
Log time on a meeting records an hour against the meeting itself, and it lands on your timesheet beside the hours you logged against issues.
Until this existed, a morning of planning was recorded against a task it was not spent on, or not recorded at all — and people choose the second, so meetings looked free. A tracker that cannot hold an hour teaches people to put it somewhere untrue.
Two things it deliberately does not do:
- It does not add the meeting's hours to the issues it produced. An hour in the room and an hour doing what the room decided are different hours. Adding them would make the meeting look like it cost nothing.
- It does not touch anyone else's entry. You can edit and remove your own; somebody else's hours are their statement, not yours, and an owner is no exception. An agent run's hours are never editable by anybody — the run is in the timeline carrying its own duration. That is the same rule the timesheet applies.
The date offered is the day the meeting was on, not today, because hours in a meeting are written down afterwards and often on another day.
Edit on an entry corrects it in place, on the same fields it was created with: the duration, the day it was spent on and the note. It is the same form, so a correction and a fresh hour cannot drift apart.
Correcting matters more than it sounds. The alternative was to remove the row and log it again, which loses when the work was recorded and turns a measured entry into a remembered one — and those are counted apart, because the time report says what share of its hours are leaning on recall. A corrected figure stays measured: whether a clock was running is a fact about how the number was arrived at, not about the number.
See Corrections.
Status
Worked out, not set. A status somebody has to remember to change is a status that lies within a week.
| Scheduled | In the future |
| Held | It has happened |
| Circulated | The notes have gone out |
| Canceled | The only status anybody sets, besides circulating |
Held used to read Awaiting minutes, and it sat on every meeting for ever: it was waiting for a second field nobody filled in. A state that is never reached is not a state, it is an accusation — so the flag went, and the banner counting meetings "without minutes" went with it.
Notes
One field. There were two — notes during, minutes after — and of twenty-one meetings four had notes and two had minutes. The field people used was not the one the page was built around.
Notes are what somebody types while the meeting happens: fragments, names, half sentences. Plain text, because they go to a model verbatim and a rich-text editor would send markup as content. Tidying and drafting write Markdown back into the same box, so you can keep typing after them.
Everything that used to hang off minutes now hangs off the notes — Tidy up with AI, Pull out action items and Circulate. The cleanup happens when the notes go out, which is the moment somebody wants it.
Tip: Tidying and accepting a draft both rewrite what you typed. There is no second copy any more. Both show you the result first and neither saves until you press the button — that review is the only safeguard, so read it.
Notes are circulated once. A record that quietly changes after people have read it is worse than a late one, so the timestamp both records the event and prevents the second send. After that the editor is closed, and so are tidying and drafting.
Everybody who was invited gets them, in their inbox and by email. The email carries the summary and a link, not the whole document: notes with action items in them are read once and referred to for months, and the action items are tracked issues whose status changes after the mail was sent.
Over the API the notes are the organiser's until they are sent, and everybody's afterwards — hiding a record from the people it was mailed to would be theatre.
Pulling out action items
Optional, off unless an operator turns it on, and one of two places in Félagi where the server calls a model — the other is tidying prose, below.
Everything an agent does happens in a CLI on hardware you control. This is the exception, so the reasoning is worth stating:
- It is not agent work. Nothing is checked out, nothing is executed, no credentials are involved. It is one text transformation on text a person just typed.
- Running it through the task queue would mean drafting only works for a team that has a daemon, a runtime and a registered agent. Meetings are a human activity — a team using Félagi as a tracker with no agents at all should be able to write notes.
- It is off unless a provider is named. An installation that does nothing makes no outbound model call, ever.
FELAGI_MINUTES_PROVIDER=anthropic
FELAGI_MINUTES_MODEL=claude-haiku-4-5-20251001
What is sent: the notes, the agenda, the meeting title and the attendee names. That is the honest cost, and it is stated here rather than in a footnote — meeting notes are often more sensitive than source code.
Why structured output rather than a summary
Asked for a summary, a model returns a paragraph that reads well and buries the two sentences somebody needed: what was decided, and who is doing what by when. Asked for a schema, it has to separate them.
The separation is also what makes the result usable. Every decision and every action item lands in its own field, so an action item can become a real issue — which is a thing a paragraph cannot become.
The instructions do the opposite of what a summariser usually does: they forbid invention. Notes are a record, and a plausible sentence in a record is worse than a gap, because a gap is visible.
Nothing is saved until you accept it
The draft opens in a panel. A draft written straight over the notes is the failure this feature is most likely to have, and only the person who called for it can tell whether the model read the room correctly.
The panel leads with what the model could not work out — the field that makes the rest trustworthy. Without somewhere to put an ambiguity, a model resolves it silently and the notes contain a decision nobody made.
The headings in the finished document are rendered by Félagi, not asked of the model. A model asked for formatted prose returns a different shape each time, and notes that look different every month are notes nobody skims correctly.
Owners
Matched by name against the people who were in the room, on the full name and then the first name. Never created, and never guessed at beyond that: an action item whose owner could not be matched is unassigned, which somebody fixes in a second. An invented user is a mess.
A due date the model got wrong is dropped rather than stopping the issue from existing.
Tidying the notes
While the notes have not been circulated, the editor offers Tidy up with AI. It is the same feature the knowledge base has, at the same boundary: before anybody else has read it. There it is publication; here it is circulation.
It is off unless an operator sets FELAGI_TIDY_PROVIDER — one switch for both surfaces,
because it is one question.
What it does. Structure and mechanics only: a wall of text gets paragraph breaks, a run of lines that is obviously a list becomes a list, a line acting as a section title becomes a heading, spelling and punctuation are corrected.
What it will not do. Add anything, rewrite your sentences, translate, or guess. A passage too unclear to structure without deciding what it means is left exactly as it was, and the question comes back to you instead. In a meeting record that matters more than anywhere else in the product: a plausible sentence in a record is a decision nobody made.
Not the notes. Notes are what somebody typed while listening, they are kept after the notes are the only copy now, so tidying rewrites them — which is why the result is shown in full before anything is saved. Turning them into a structured write-up, with the action items pulled out as issues, is what Pull out action items does.
Nothing is saved. You get a list of what changed and what it left alone; accepting puts it in the editor, and Save is still a separate press. Then Circulate, which is once and final — after that the notes are the record and neither editing nor tidying is offered.
Standing meetings
A recurring meeting is the one cost nobody totals. Each occurrence is an hour, and an hour is nothing, and forty of them are a working week that produced three action items of which one got done. That sentence is the whole argument for or against a meeting, and every part of it was already recorded — occurrences, hours logged against being in the room, and action items, which are issues carrying a meeting id. Nothing added it up.
The meetings page now does, per series:
Weekly platform sync · 14 held · 21h · 6 action items, 2 done
Only occurrences that have happened. A series generated three months ahead has not cost anything yet, and a series that has never met says nothing for itself either way.
Hours are what people logged against the meeting, on their timesheets — see Timesheets. A meeting nobody logs time against reads no hours logged rather than as free.
Not there yet
- Weekly intervals only. "The last Friday of the month" and "the 31st" are two different intentions and February disagrees with both, so a monthly rule needs a policy nobody wants to read.
- One series per meeting. A sync that moves permanently is a new series.
- No replies at all, inbound or otherwise. The
.icscarries no participation status and asks for none, so each person can accept it in their own calendar — Félagi simply does not keep the answer. Who is coming is who is on the list. - No attachments on a meeting, and no meeting record in the knowledge base — though an article can link to one.
- No series over the API, and no sending invitations or circulating notes over it either — both are irreversible broadcasts. Reading and scheduling are there.
- Not in the import or the export.
- All-day meetings are one day. A three-day offsite is three meetings. A length in days would need to decide what a weekend in the middle means, and there is no answer that is right for both a course and a conference.
- No attendees who are not members. An external participant has no account, and inviting an address Félagi cannot show a page to would be an email pretending to be a feature.
- Agents do not attend. The attendee column is
user_idand not a morph, because a polymorphic column where one of the two values can never appear is worse than a plain one.