File size: 3,756 Bytes
488d96b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | # Services and dependencies
English | [中文](service.zh.md)
A service is a capability one plugin exposes to other plugins. `inject` declares the services a plugin requires.
## What is a service?
In Harness, `tools`, `llm`, and `agents` are services. Each is a named capability mounted on `ctx`:
```ts ignore-check
ctx.tools // ToolRuntime service
ctx.llm // LLM service
ctx.agents // Agent service
```
Any plugin can provide a service for other plugins to consume.
## Consume a service
Declare `inject` to use an existing service:
```ts ignore-check
export const inject = ['tools']
export function apply(ctx: Context) {
// ctx.tools exists and is ready here.
ctx.tools.register(/* ... */)
}
```
When `apply` runs, every service declared by `inject` is ready. If a service is not ready, the plugin waits instead of running.
## Provide a service
### Extend Service
```ts
import { Service, type Context } from '@deepseek-ai/cordis'
export default class MetricsService extends Service {
static inject = ['llm'] // A service may depend on other services.
constructor(ctx: Context) {
super(ctx, 'metrics') // 'metrics' is the service name.
}
// Public service method.
record(event: string, value: number) {
// ...
}
}
```
After loading this plugin, consumers access the service as `ctx.metrics`:
```ts ignore-check
export const inject = ['metrics']
export function apply(ctx: Context) {
ctx.metrics.record('tool_call', 1)
}
```
### Declare its type
Use TypeScript declaration merging to type `ctx.metrics`:
```ts
import { Service, type Context } from '@deepseek-ai/cordis'
declare module '@deepseek-ai/cordis' {
interface Context {
metrics: MetricsService
}
}
export default class MetricsService extends Service {
constructor(ctx: Context) {
super(ctx, 'metrics')
}
record(event: string, value: number) { /* ... */ }
}
```
## Dependency behavior
### Required and optional dependencies
```ts ignore-check
// Required: the plugin does not load while the service is absent.
export const inject = ['tools']
// Optional: omit inject and query with ctx.get() at the use site.
export function apply(ctx: Context) {
const metrics = ctx.get('metrics')
metrics?.record('plugin_loaded', 1)
}
```
### When a service disappears
If a required service disappears while the application is running, for example because its provider unloads:
1. Dependent plugins dispose automatically.
2. They load again when the service returns.
This prevents a plugin from calling a service that no longer exists.
## Service isolation
`cordis.yml` can isolate services so separate plugin groups see separate instances of the same service:
```yaml
- id: group-a
name: '@deepseek-ai/cordis-plugin-group'
group: true
isolate:
shell: true
config:
- name: '@deepseek-ai/dsh-bash-local'
config:
timeoutMs: 5000
- name: './src/plugin-a.ts'
- id: group-b
name: '@deepseek-ai/cordis-plugin-group'
group: true
isolate:
shell: true
config:
- name: '@deepseek-ai/dsh-bash-local'
config:
timeoutMs: 60000
- name: './src/plugin-b.ts'
```
`plugin-a` and `plugin-b` each see the Bash instance in their own group, with no cross-group effect.
## Built-in Harness services
The repository generates the service names, public methods, and source locations into each service's [subsystem page](../../../subsystems/core.md). Use those generated regions and the service's TypeScript interface while developing a plugin; do not maintain a second static list.
## Next steps
- [Event system](./events.md) — communicate between plugins without tight coupling
- [Capability layering](../practice/index.md) — use services as capability interfaces
|