Your first intent
This guide walks through building a Create Calendar Event intent from
scratch — all the way from empty file to production Swift. By the end you’ll
understand defineIntent, the param.* helpers, entitlements, and Info.plist
keys.
The goal
We want Siri to be able to say:
“Hey Siri, create a calendar event called ‘Dentist’ tomorrow at 2pm for 30 minutes.”
That means our intent needs:
- A title and description (shown in Shortcuts)
- A domain — we’ll use
productivity - Four parameters: title, start date, duration, and an “all day” flag
- The calendars entitlement so iOS actually lets us write to EventKit
- An Info.plist key so Siri can ask for calendar permission
Write it
Create a file at intents/CreateCalendarEvent.intent.ts:
import { defineIntent, param } from "@axint/compiler/sdk";
export default defineIntent({ name: "CreateCalendarEventIntent", title: "Create Calendar Event", description: "Creates a new event on the user's calendar.", domain: "productivity",
params: { eventTitle: param.string("Title of the event"), startDate: param.date("When the event starts"), durationMinutes: param.int("Length of the event in minutes"), isAllDay: param.boolean("Whether the event is all-day", { optional: true, default: false, }), },
entitlements: ["com.apple.developer.calendars"], infoPlistKeys: ["NSCalendarsUsageDescription"],});Compile it
axint compile intents/CreateCalendarEvent.intent.ts \ --out ios/Intents/CreateCalendarEventIntent.swift \ --emit-info-plist \ --emit-entitlements \ --sandbox \ --formatYou get three files:
| File | What it is |
|---|---|
CreateCalendarEventIntent.swift | The compiled Swift intent |
CreateCalendarEventIntent.plist.fragment.xml | <key>/<string> pairs to merge into your Info.plist |
CreateCalendarEventIntent.entitlements.fragment.xml | Entitlement dictionary to merge into your .entitlements |
What the Swift looks like
import AppIntentsimport Foundation
struct CreateCalendarEventIntent: AppIntent { static var title: LocalizedStringResource = "Create Calendar Event" static var description = IntentDescription( "Creates a new event on the user's calendar." )
@Parameter(title: "Title of the event") var eventTitle: String
@Parameter(title: "When the event starts") var startDate: Date
@Parameter(title: "Length of the event in minutes") var durationMinutes: Int
@Parameter(title: "Whether the event is all-day", default: false) var isAllDay: Bool
func perform() async throws -> some IntentResult { // TODO: call EventKit to actually create the event return .result() }}Note how:
param.intmapped to SwiftInt(notDoubleorNSNumber)- The optional
isAllDayparameter got a real Swiftdefault: false - The description shows up as a
LocalizedStringResourcefor free localization
Fill in perform()
Axint generates the shape of perform() but deliberately leaves the body
empty — you plug into EventKit, HealthKit, HomeKit, or your custom app logic
however you like.
func perform() async throws -> some IntentResult { let store = EKEventStore() try await store.requestFullAccessToEvents()
let event = EKEvent(eventStore: store) event.title = eventTitle event.startDate = startDate event.endDate = startDate.addingTimeInterval(Double(durationMinutes) * 60) event.isAllDay = isAllDay event.calendar = store.defaultCalendarForNewEvents try store.save(event, span: .thisEvent)
return .result()}Next steps
- Entitlements & Info.plist →
- Templates → — ten more working intents
- defineIntent() reference →