Skip to content
docs
UseBuildChangelog
Open Lumin

Examples

muhurta-scheduler

A date picker for the electional family. Choose what you are scheduling from the catalog, name the hours and the date range you can actually use, and provide the native's birth details, since 14 of the 15 electional tools read the running dasha lord of a real person's chart. The result is one moment with a stated reason, or up to three on a genuine tie, never a ranked list.

Tool chain

get_election_catalog runs first and is the one person-free call: it lists the event types and their house groups, which populates the event-type dropdown. The elect route then takes the native's birth data directly and calls one named tool, selected in code from the catalog choice and never guessed by the model: find_wedding_muhurta, find_exam_time, find_interview_time, find_meeting_time, find_contract_signing_time, find_business_launch_time, find_travel_departure_time, find_property_muhurta, find_surgery_time, or the generic find_election_window for anything without a named tool.

When the user supplies a short list of candidate dates instead of an open range, rank_candidate_dates replaces the search call: the user names the 2 to 10 dates they can actually do, and the tool orders only those, never proposing a date outside the list. get_panchang runs last, for the panchang detail of the winning moment.

Inputs

  • name, birth_date, birth_time, location_name for the native
  • eventType, one key from the election catalog
  • preferredHours, the hours of day the user can actually use. The single highest-impact parameter: a search with no hour constraint returns moments nobody can act on
  • rangeStart and rangeEnd, for the search mode
  • candidateDates, optional, for the rank mode: a short list instead of an open range

Call it

typescript
// Three routes, three allowlists. The catalog call needs no birth data at all.
const ALLOWED_TOOLS_CATALOG = ["get_election_catalog"] as const;

const ALLOWED_TOOLS_ELECT = [
  "find_wedding_muhurta", "find_exam_time", "find_interview_time",
  "find_meeting_time", "find_contract_signing_time",
  "find_business_launch_time", "find_travel_departure_time",
  "find_property_muhurta", "find_surgery_time",
  "find_election_window",        // the long tail, for events with no named tool
  "get_muhurta_advanced",        // an older method, used as a second opinion
  "get_panchang", "get_choghadiya_today",
  "get_boundary_warnings",
] as const;

const ALLOWED_TOOLS_RANK = ["rank_candidate_dates", "get_boundary_warnings"] as const;

const result = await runLumin({
  allowedTools: ALLOWED_TOOLS,
  system: buildSystemPrompt(input.eventType), // names the one tool this run may use
  user: buildUserPrompt(input),
  maxTokens: 16000,
  effort: "xhigh",
  signal: req.signal,
});

const parsed = ensureShape(
  parseJsonBlock<MuhurtaResponse>(result.text),
  validateShape,
);

Fourteen tools sit on the allowlist so any event type can be served, but the system prompt is built per request to name only the one tool this event needs, on top of the allowlist already closing off everything else. A typical run calls 5 to 7 tools.

Response shape

json
{
  "resolved_location": { "latitude": 6.9271, "longitude": 79.8612, "utc_offset_minutes": 330, "note": "Colombo, Sri Lanka" },
  "event": {
    "key": "wedding",
    "label": "Wedding",
    "house_group": [1, 2, 7, 11],
    "provenance": "Named tool: find_wedding_muhurta"
  },
  "mode": "search",
  "result": {
    "moments": [
      {
        "datetime": "2027-06-12T10:40:00+05:30",
        "reason": "Ascendant sub lord signifies 2, 7 and 11 with no connection to 6, 8 or 12; Venus dasha running.",
        "house_group": [1, 2, 7, 11]
      }
    ],
    "tie": false
  },
  "panchang_context": {
    "tithi": "Shukla Ashtami", "nakshatra": "Uttara Phalguni", "sunriseUTC": "2027-06-12T00:31:00Z"
  },
  "disclaimer": "One elected moment with a stated reason. Not a ranked list, and not a guarantee of outcome."
}

Screens

  • An event-type selector drawn from the catalog
  • A birth-details form for the native
  • An hours-of-day picker (the highest-impact input) and a date-range or candidate-dates toggle
  • A result card showing the one moment (or up to three on a tie), each with its own stated reason, never a numbered ranking

Never a score

The UI deliberately has no place to put a number. There is no star rating, no percentage, no bar chart, because the underlying tools return none. A result card with an empty slot where a score "should" go is a hint the layout was copied from a generic scheduling tool; redesign the card around the reason string instead.

The interesting engineering detail

Each named tool bakes its event key server-side through a fixed-parameter mechanism, so a model reasoning about the request cannot be talked into a different event mid-conversation. The dropdown choice, not the model's interpretation of the free-text question, decides which house group governs the search. That matters specifically because electing houses are not the houses that constitute the matter (the corpus elects surgery on 1, 5, 11, the "recovery and cure" houses, while surgery is promised on 1, 6, 8, 12), so a model guessing the wrong tool from a vague prompt would search the wrong houses entirely.

Where to next