

# Effect SDK [#effect-sdk]

Use the Effect SDK when your application already composes services with Effect,
or when an in-process transport needs the full calculator run response. Most
server-side TypeScript applications should start with the [Plain SDK](/sdk/plain-sdk).

## Runtime graph [#runtime-graph]

```ts
Production: SDK Effect full run

Effect consumer
  -> calculateRunRequest(descriptor, request)
    -> PublicCalculatorService.calculate
      -> CalculatorRunResponse
    -> descriptor output decode for response.report
    -> typed CalculatorRunResponse with narrowed report

Report-only helpers
  -> calculateReportRequest(...)
    -> calculateRunRequest(...)
    -> response.report
  -> calculateReport(...)
    -> calculateReportRequest(...)
```

## Return the full run response [#return-the-full-run-response]

Use `calculateRunRequest` when you need the canonical `CalculatorRunResponse`
shape with a descriptor-decoded report type. Omitted request fields use their
Schema defaults. Explicit context and help use nested Options: outer `None`
means a missing key, `Some(None)` means a present undefined key and
`Some(Some(value))` means a present value. JSON clients keep the usual optional
fields; the codec handles this conversion.

```ts
import { audFromCents } from "@taxkit/core/primitives";
import { calculateRunRequest } from "@taxkit/sdk/effect";
import { AuAnnualIncomeTaxCalculation } from "@taxkit/sdk/au/effect";
import { Effect, Option } from "effect";

const effect = Effect.gen(function* () {
  const taxableIncome = yield* audFromCents(9_000_000);
  return yield* calculateRunRequest(AuAnnualIncomeTaxCalculation, {
    payload: {
      facts: { taxableIncome },
      jurisdiction: Option.some(
        Option.some(AuAnnualIncomeTaxCalculation.jurisdiction)
      ),
      taxYear: Option.some(Option.some(AuAnnualIncomeTaxCalculation.taxYear)),
    },
  });
});
```

## Return only the report [#return-only-the-report]

Use `calculateReportRequest` when you have a full request payload but only need
the report.

```ts
import { audFromCents } from "@taxkit/core/primitives";
import { calculateReportRequest } from "@taxkit/sdk/effect";
import { AuAnnualIncomeTaxCalculation } from "@taxkit/sdk/au/effect";
import { Effect, Option } from "effect";

const effect = Effect.gen(function* () {
  const taxableIncome = yield* audFromCents(9_000_000);
  return yield* calculateReportRequest(AuAnnualIncomeTaxCalculation, {
    payload: {
      facts: { taxableIncome },
      jurisdiction: Option.some(
        Option.some(AuAnnualIncomeTaxCalculation.jurisdiction)
      ),
      taxYear: Option.some(Option.some(AuAnnualIncomeTaxCalculation.taxYear)),
    },
  });
});
```

Use `calculateReport` when you already have descriptor-typed facts:

```ts
import { Cents, aud } from "@taxkit/core/primitives";
import { calculateReport } from "@taxkit/sdk/effect";
import { AuAnnualIncomeTaxCalculation } from "@taxkit/sdk/au/effect";

const effect = calculateReport(AuAnnualIncomeTaxCalculation, {
  taxableIncome: aud(Cents.make(9_000_000)),
});
```

## Use an Effect client [#use-an-effect-client]

```ts
import { Cents, aud } from "@taxkit/core/primitives";
import { createClient } from "@taxkit/sdk/effect";
import {
  AuIncomeTax2025_26Module,
  AuAnnualIncomeTaxCalculation,
} from "@taxkit/sdk/au/effect";

const client = createClient(AuIncomeTax2025_26Module);

const effect = client.calculations.calculateReport(
  AuAnnualIncomeTaxCalculation,
  { taxableIncome: aud(Cents.make(9_000_000)) }
);
```

## Requirements [#requirements]

Effect helpers require `PublicCalculatorService` in the environment. Each
plain SDK client owns its runtime and must be disposed when finished; direct
helpers clean up before returning. The Effect SDK leaves service provision to the
consumer so application layers and tests can choose the calculator service
implementation.

## Related pages [#related-pages]

* [Plain SDK](/sdk/plain-sdk)
* [Schemas](/sdk/schemas)
* [Choose SDK or HTTP API](/start/choose-sdk-or-api)
